DEV Community

Keo Fung | FormLM
Keo Fung | FormLM

Posted on

I Let Claude Desktop Build My Entire Assessment Form. Here's What Happened.

Series: Building an AI-Native Assessment Platform (11/20)

I've been building FormLM's CLI and MCP server for a while now. The architecture is solid, the tools are defined, the zod schemas are clean. But there's a difference between "the code works" and "watching an AI agent actually use your tools to build something real."

Last weekend I decided to stop testing in isolation and let Claude Desktop build a complete assessment form from scratch — using only the MCP tools I'd built. No hand-holding, no manual CLI commands, no editing the form in the web UI afterward. Just Claude, the MCP server, and a natural language prompt.

Here's the full timeline, including the parts where it broke.

The Setup

I'd already installed formlm-cli globally and configured it in Claude Desktop's config:

{
  "mcpServers": {
    "formlm": {
      "command": "formlm-cli",
      "args": ["mcp"]
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

I'd logged in via formlm-cli auth login beforehand so the token was already stored. Claude didn't need to authenticate — it could just start using the tools.

The Prompt

I gave Claude this instruction:

"Build a burnout self-assessment form. Three dimensions: exhaustion, cynicism, and professional efficacy. Use the Maslach framework. Each dimension needs 3 questions on a 1-7 Likert scale. Add one reverse-scored item for the efficacy dimension. Then publish it and give me the URL."

That's it. No field IDs, no type names, no scoring configuration details. I wanted to see if Claude could figure out the right tool calls from the schema descriptions alone.

What Claude Did (Step by Step)

Step 1: Create the app

Claude called app_create with the name "Burnout Self-Assessment" and a brief description. Got back an app ID. Straightforward.

Step 2: Check available field types

This surprised me. Before adding any fields, Claude called field_schema to see what field types were available. It didn't assume it knew the types — it checked. The response listed all supported types including scale, radio, input, textarea, etc.

Then it called field_config --type scale to see what properties a scale field accepts. It found min, max, and the scoring options.

This was the moment I realized the schema descriptions mattered more than I thought. Claude was reading them like documentation. The .describe() strings on every zod field weren't just metadata — they were the instructions the AI followed.

Step 3: Add the exhaustion dimension (3 fields)

Claude added three scale fields for the exhaustion dimension:

field_add: id=ex1, type=scale, title="I feel emotionally drained by my work", min=1, max=7
field_add: id=ex2, type=scale, title="I feel used up at the end of the workday", min=1, max=7
field_add: id=ex3, type=scale, title="I feel fatigued when I get up in the morning and have to face another day", min=1, max=7
Enter fullscreen mode Exit fullscreen mode

So far so good. The field IDs were sensible (ex1, ex2, ex3). The titles were actual Maslach Burnout Inventory items, not made-up questions. Claude knew the framework.

Step 4: Add cynicism and efficacy

Same pattern for cynicism (cy1, cy2, cy3) and professional efficacy (pe1, pe2, pe3).

Here's where it got interesting. For the efficacy dimension, I'd asked for a reverse-scored item. Claude added:

field_add: id=pe3, type=scale, title="I do NOT feel I am making an effective contribution to my organization", min=1, max=7
Enter fullscreen mode Exit fullscreen mode

The "NOT" was Claude's way of making a reverse-scored item — by phrasing the question negatively so that a high score indicates low efficacy. Not how I'd implement reverse scoring (I'd use the --negFields mechanism in the scale configuration), but for a form-only build without scale config, it was a reasonable approach.

Step 5: Publish

Claude called share_publish with the app ID, then share_url to get the fill-in URL. The whole thing came back as a link.

Total time: about 90 seconds. Nine fields across three dimensions, published, with a live URL.

Where It Got Weird

The form worked. People could fill it out. But there were a few things that made me realize the tools weren't quite enough on their own.

No dimensional grouping. Claude added nine fields, but they were just nine individual scale questions. There was no "dimension" concept in the form — that lives in the Scale module, which the MCP server doesn't expose yet. So the form collected answers but couldn't compute dimension scores. That's a gap I need to fill.

No scoring logic. Even if dimensions were configured, the MCP tools don't include scale configuration commands (by design — those are in the whitelist's blocked list because they're administrative). So the form was a data collection tool, not an assessment engine. To get scoring, I'd need to configure the Scale module separately.

The reverse-scored item was textual, not structural. Claude handled reverse scoring by writing a negatively-phrased question. That works for data collection but doesn't tell the scoring engine to invert the score. The real fix is the --negFields parameter in scale configuration — but that's not exposed via MCP.

What I Learned

The MCP tools are good at form construction. Claude figured out the right field types, the right scale ranges, the right question wording — all from the schema descriptions. The .describe() strings did their job.

But form construction is only the first 20% of an assessment. The other 80% — dimensional scoring, tier assignment, report generation — lives in modules the MCP server doesn't expose. That's intentional (security), but it means an AI agent can build the input form but not the assessment logic.

My next step: figure out how to safely expose scale configuration to the MCP server without opening up the administrative commands that shouldn't be AI-accessible. The whitelist exists for a reason, but there's a middle ground between "AI can add fields" and "AI can reconfigure scoring rules."

For now, the workflow is: Claude builds the form, I configure the scoring by hand. That's still way faster than building the whole thing manually. But it's not the fully AI-driven assessment pipeline I want it to be.

Still — watching Claude build a complete, publishable form in 90 seconds from a one-sentence prompt was a moment. The tools work. The schemas work. There's just more pipeline to expose.


This is part of a series on building AI-native tooling for FormLM. The CLI and MCP server are open source — check them out at github.com/formlm/cli or try the platform at formlm.me.

Top comments (0)