Other Clients
Cursor, Windsurf, and anything you write yourself: the generic path, and what to check when a client misbehaves.
No client-specific code lives in Surface's MCP server. If your tool speaks Streamable HTTP MCP, it connects with a URL and a header.
{
"mcpServers": {
"surface-forms": {
"url": "https://app.withsurface.com/mcp",
"headers": { "Authorization": "Bearer <your-api-key>" }
}
}
}Clients with a Written-up Config
| Client | Notes |
|---|---|
| Cursor | Settings UI or .cursor/mcp.json. Config → |
| Windsurf | ~/.codeium/windsurf/mcp_config.json, serverUrl key. Config → |
| Your own agent | Any MCP client library. Nothing here is Surface-specific |
Any other editor that supports Streamable HTTP takes the generic block above. These are the two clients with a written-up config in API setup.
Clients That Configure Headers but Not URLs
For hosts that set headers but not query strings:
{
"headers": {
"Authorization": "Bearer <your-api-key>",
"X-Surface-Tool-Families": "content"
}
}?tools= wins if both are present. Full rules in
Tool bundles.
Writing Your Own Client
Three behaviours worth coding against:
Schemas are discoverable. list_component_types,
describe_component_type and get_tool_schema return the real shapes at
runtime, so you never hard-code a payload that a release can change.
Unknown selections fail open. A ?tools= list with a typo falls back to
everything rather than producing a zero-tool server. A known tool your
credential excludes is silently skipped, so fewer tools than you expected is a
permissions problem, not a spelling one.
Form writes are drafts. publish_form is the only call that changes what a
visitor sees.
When Something Does Not Work
Check the tool count
A default connection loads 45 tools. Fewer usually means ?readonly=1 or a
restricted credential; 128 means ?tools=all.
Check the transport
Streamable HTTP. There is no local process and no Docker container, so a client that can only launch a stdio server needs a bridge.
Check the header
Authorization: Bearer <key>, with the word Bearer. This is the single
most common failure.
Check the environment
Every call is scoped to the credential's environment. A tool returning an empty list is often a correct answer about the wrong environment.
More in MCP troubleshooting.