npx skills add ...
npx skills add celigo/ai --skill building-mcp-servers
Build Celigo MCP server resources -- endpoints that expose Tools and builder-mode APIs to external AI agents and MCP clients. Use when creating MCP servers, linking tools or APIs, or configuring annotations and overrides.
npx skills add celigo/ai --skill building-mcp-servers
An MCP server is a Model Context Protocol endpoint that exposes Celigo Tools and builder-mode APIs as callable tools for external AI agents and MCP clients. Concerns when building an MCP server:
relativeURI that forms the server's URL pathreadOnlyHint, destructiveHint, idempotentHint, openWorldHint) that help AI agents decide when and how to call a tooltools[] and apis[] entries within the serverMCP servers support configurable authentication of their own -- Celigo OAuth (the default), an external IdP, or static API tokens, gated by mcp:read / mcp:write scopes (see Authentication and Scoping). Outbound calls to external systems use the connections referenced by the underlying tools and APIs.
Used alongside tools and APIs. The MCP server is a thin exposure layer -- all processing logic lives in the referenced Tool and API resources.
MCP servers combine two types of entries:
tools[])Reference Celigo Tool resources. Each tool becomes an MCP tool endpoint. The tool's input.schema must have type: "object" at the root to comply with the MCP specification. Tool entries support annotations (behavior hints) and overrides (per-server connection/resource customization).
apis[])Reference Celigo builder-mode API resources. Each API becomes an MCP tool endpoint. Only type: "builder" APIs are supported -- script-mode and legacy APIs cannot be exposed via MCP. API entries do not support annotations or overrides.
In production, most MCP servers expose APIs only. Servers that combine both tools and APIs are less common but valid for mixed read/write patterns (e.g., tools for writes with annotations, APIs for lookups).
| You need to... | Use tool entry | Use API entry |
|---|---|---|
| Expose reusable logic with connection flexibility | Yes | -- |
| Hint behavior to AI agents (read-only, destructive) | Yes (annotations) | -- |
| Swap connections per-server without modifying the resource | Yes (overrides) | -- |
| Expose a builder-mode API as an MCP endpoint | -- | Yes |
| Expose a script-mode or legacy API | Not supported | Not supported |
Every MCP server needs at minimum:
name -- human-readable labelrelativeURI -- unique URI path segment (must start with /, single segment, alphanumeric + underscores + hyphens)Each tool entry needs: _toolId, name
Each API entry needs: _apiId, name
All schemas are in references/schemas/:
| Schema | What it defines |
|---|---|
| request.yml | Top-level MCP server fields (name, relativeURI, description, disabled, tools, apis) |
| response.yml | MCP server response shape (includes _id, timestamps, sandbox) |
| io-tool.yml | Tool entry schema (_toolId, name, disabled, annotations, overrides) |
| api-tool.yml | API entry schema (_apiId, name, disabled) |
| annotations.yml | MCP behavior hints (title, readOnlyHint, destructiveHint, idempotentHint, openWorldHint) |
| overrides.yml | Per-server overrides for connections, exports, imports, and routers |
Before creating anything, determine what capabilities the MCP server should offer to AI agents. Each capability maps to either a Tool or a builder-mode API. Group related capabilities under a single server with a meaningful relativeURI.
Look for tools and APIs that can be reused before creating new ones.
MCP servers reference tools and APIs -- these must exist first. Build order:
building-tools skill). Ensure input.schema has type: "object" at root for MCP compatibilitybuilding-apis skill). Ensure type: "builder" is setEach entry (tool or API) needs a name that becomes the MCP tool name visible to AI agents. Names must:
tools[] and apis[] entries in the serverget_customer, create_order, validate.input)Annotations are optional MCP-standard hints that help AI agents decide when and how to call a tool. Set them based on what the underlying tool actually does:
readOnlyHint: true -- tool only reads data, no side effects (e.g., a lookup)destructiveHint: true -- tool deletes or permanently modifies dataidempotentHint: true -- calling multiple times with the same input produces the same resultopenWorldHint: true -- tool interacts with external APIs where results may vary between callsAnnotations are hints only -- they are not enforced by the server.
Overrides let you customize a tool's internal resources for this specific MCP server without modifying the tool definition. This enables reusing the same tool across multiple servers with different configurations.
The most common override is connection overrides -- mapping the tool's abstract connection references to concrete connections for this server. Override entries use _abstractId (the connection ID in the tool definition) and _id (the concrete connection to use instead).
Export, import, and router overrides are also available but rarely used in practice.
Reference the Schema Index for exact field schemas. Every MCP server needs at minimum: name and relativeURI. Add tools[] and/or apis[] entries to expose capabilities. Set disabled: false to enable the server (at least one tool or API entry must also be enabled).
Deciding who can call a server is the second design decision after deciding what it exposes. MCP servers have their own configurable authentication, independent of the connections their underlying tools use. Celigo OAuth and API tokens can be enabled at the same time on one server -- a common shape when a server serves both human users (OAuth) and automation (tokens).
mcp:read, mcp:write, or both). With External, the Users list is not shown and per-user downstream connections are not available. Provider limits to check first: Auth0 requires the Resource Parameter Compatibility Profile on its application, and Microsoft Entra ID and Google Identity are not currently supported for MCP OAuth.mcp:read / mcp:write split.Default to Celigo OAuth, and add an API token alongside it when automation is in scope. Reach for an external IdP only when the consumer explicitly requires a specific provider.
mcp:read vs mcp:writeEvery OAuth path (Celigo or external) requires the issued token to carry MCP scopes:
mcp:read -- non-destructive operations, such as listing available tools (tools/list) and invoking tools whose underlying Tool or API has no side effects.mcp:write -- operations that may change data or state.The scope is checked on every request; a structurally valid token missing the required scope is rejected. Grant the minimum scope a consumer needs -- a read-only partner should not receive mcp:write. The scope claim usually lives in the standard OAuth scope or scp claim, depending on the IdP.
Before creating or updating an MCP server, verify:
name is set and descriptiverelativeURI starts with /, contains a single path segment, uses only alphanumeric characters, underscores, and hyphensrelativeURI is unique across all MCP servers in the account_toolId references in tools[] point to existing Tool resources_apiId references in apis[] point to existing builder-mode API resources (not script-mode or legacy)tools[] and apis[] entries in the serverinput.schema has type: "object" at rootdisabled: false) if the server itself is enabled_abstractId to valid concrete connection IDsset command handles this automatically.type: "builder" APIs work in MCP servers. If you get a validation error on an API entry, verify the referenced API has type: "builder" set.type: "object". The MCP specification requires tool inputs to be JSON objects. If a tool's input.schema has a different root type (e.g., array, string), it cannot be exposed via MCP.readOnlyHint: true does not prevent the tool from writing data. The AI agent may ignore annotations entirely.get_customer in tools[] conflicts with an API also named get_customer in apis[]. Names must be unique across the combined set.apis[] do not support annotations or overrides. To customize an API's behavior per-server, modify the API resource itself.disabled: false on the server alone is not sufficient -- at least one tool or API within it must also have disabled: false./preview and /logs endpoints for MCP servers are not accessible via bearer token -- they require the UI session.type: "mcp") that consumes an external MCP server, so Celigo calls out. They share the word "MCP" and are configured in different places -- confusing the two is a common mistake here. If the goal is to wire Celigo to consume someone else's MCP server, reach for an MCP connection, not this resource.| Error | Cause | Fix |
|---|---|---|
| 422 on create/update | Missing required fields or invalid relativeURI format | Check name and relativeURI; ensure URI starts with / and is a single valid segment |
422 _toolId not found | Referenced tool does not exist or was deleted | Verify the tool exists with celigo tools get <id> |
422 _apiId not found | Referenced API does not exist or was deleted | Verify the API exists with celigo apis get <id> |
422 duplicate tool name | Two entries share the same name | Ensure all names across tools[] and apis[] are unique |
422 relativeURI already in use | Another MCP server in the account uses the same URI | Choose a different relativeURI; check with celigo mcp-servers list |
422 invalid API type | API entry references a script-mode or legacy API | Only type: "builder" APIs are supported; check with celigo apis get <id> |
422 input schema invalid | Tool's input.schema root type is not object | Update the tool's input schema to have type: "object" at root |
| Server enabled but not accessible | All tool/API entries are disabled | Enable at least one entry with disabled: false |
# CRUD
celigo mcp-servers list
celigo mcp-servers get <id>
celigo mcp-servers create < mcp-server.json
celigo mcp-servers update <id> < mcp-server.json
celigo mcp-servers set <id> key=value [key2=value2 ...]
celigo mcp-servers delete <id>
# Discovery
celigo account search "<keyword>"
celigo tools list
celigo apis list