Authoring agent integrations
Build your own MCP tools and skills that compose with ours. Same primitives, same auth, same audit log.
You can extend the agent surface in three places. All three are first-class — your tools and skills sit alongside ours, share the same Authorization: Bearer mg_pat_* or OAuth credential, and land in the same audit log.
1. Custom MCP tools
Drop a TypeScript module that exports a register(server, ctx) function and ship it as a tarball or a private npm package. The agent's .mcp.json loads it the same way it loads ours.
// my-org/mcp-extras/src/index.ts
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"
import { z } from "zod"
export function register(
server: McpServer,
ctx: () => { orgId: string; userId: string },
) {
server.registerTool(
"myorg.deploy_status",
{
description: "Return the latest deploy state for a service in our infra.",
inputSchema: { service: z.string() },
},
async (args) => {
const status = await fetch(
`https://infra.myorg.dev/status/${args.service}`,
).then((r) => r.json())
return {
content: [{ type: "text", text: `${args.service}: ${status.state}` }],
structuredContent: status,
}
},
)
}Conventions we strongly recommend:
- Namespace your tool names with your org slug —
myorg.deploy_status, notdeploy_status. Prevents collisions with built-ins or future ours. - Mirror our confirmation flow for any mutation. On the first call without
confirm: true, returntoolError("CONFIRMATION_REQUIRED", …)with apreviewpayload. The agent shows the preview before re-issuing. - Re-assert your own auth if your tool calls a private API — our PAT/OAuth scope is for the Synapse Garden control plane only. Forward your own token in
providerOptionsor read it from env in the customer's MCP host.
2. Custom skills
Author one or more skill bundles in the Anthropic Agent Skills format. Drop them under .claude/skills/ (project-scoped) or distribute them as an npm package.
# Local-only — drop your bundle into the repo
.claude/skills/myorg-internal-api/
SKILL.md
recipes/auth.ts
recipes/idiomatic-call.tsCross-reference our skills from yours:
---
name: myorg-internal-api
description: Use when calling the MyOrg internal-api with the AI SDK.
---
# MyOrg internal-api
See `recipes/auth.ts` for the bearer header convention.
See `recipes/idiomatic-call.ts` for a typed `streamText` example.
## When to load companion skills
- For Synapse Garden setup → load `synapse-garden-quickstart`.
- For tool use → load `synapse-garden-tools`.The agent loads both side by side, so a single prompt can compose your guidance with ours.
3. Custom prompts
server.registerPrompt(...) is a small surface that's easy to overlook. A prompt is a named, parameterized recipe the agent can invoke when the user asks something vague — the prompt suggests a sequence of tool calls without executing them.
Use this for cross-tool flows that span our APIs and yours:
server.registerPrompt(
"myorg.deploy-and-watch",
{
description:
"Ship the current branch, then watch error rates against Synapse Garden for 10 minutes.",
argsSchema: { service: z.string() },
},
async ({ service }) => ({
messages: [
{
role: "user" as const,
content: {
type: "text" as const,
text: `Run myorg.deploy(${service}), then call \`tail_errors\` every 60s for 10 minutes. Return a summary.`,
},
},
],
}),
)The agent picks it up under "available prompts," shows the user, and on confirmation runs the tool sequence.
Listing in the marketplace
Phase E (/docs/agents/index → roadmap) opens a public marketplace at /app/agent-marketplace. To list your extension you'll need:
- A signed manifest (we'll publish the schema)
- A short security review for any tool that mutates customer state
- Versioned releases pinned to a semver range
Until then, your extensions are private — they install only into orgs you control. Email hi@synapse.garden if you'd like a slot in the early-listing queue.
Audit + observability
Every customer-authored MCP tool that the platform runs through our hosted server is automatically:
- Audit-logged with
actor_user_id,tool_name,args_hash, and the MCPclientInfofrom the protocol handshake. - Rate-limited at 60 RPM per token across the whole control plane.
- Subject to scope checks — your tool declares which scopes it needs; tokens without those scopes get
INSUFFICIENT_SCOPEbefore your handler runs.
You don't have to wire any of this — it's the same machinery the built-in tools use.