Guides
Add your first connector surfaces#
agent-connector starts after the neutral MCP server works. This page shows the first useful expansion path: declare the server, verify the install, then add host surfaces only when they solve a real user problem.
1. Use a staged expansion order#
Do not add every surface because it exists. Each surface answers a different question: what the model can call, what the host triggers, what the user invokes, what the host displays, and what context files it loads.
Plain MCP server works
-> one host can call one read-only tool
-> defineConnector({ server })
-> install/doctor proves host config rendering
-> add static surfaces when users need reusable context
-> add hooks for lifecycle policy where hosts support hooks
-> add statusline for glanceable state
-> add actions for deliberate user commands2. Start server-only#
The first connector config should only wrap the MCP server you already tested. That keeps install/doctor failures separate from hook or surface handler failures.
// agent-connector.config.mjs
import { fileURLToPath } from "node:url";
import { defineConnector } from "@ken-jo/agent-connector/sdk";
const serverPath = fileURLToPath(new URL("./my-mcp-server.mjs", import.meta.url));
export default defineConnector({
server: {
transport: "stdio",
command: "node",
args: [serverPath],
},
});3. Add runtime surfaces deliberately#
Statusline and actions are runtime-dispatched handler surfaces. They are re-imported from the connector module, so keep handlers deterministic, fast, and safe to run without ambient process state.
import {
defineAction,
defineConnector,
defineStatusline,
} from "@ken-jo/agent-connector/sdk";
import { fileURLToPath } from "node:url";
const serverPath = fileURLToPath(new URL("./my-mcp-server.mjs", import.meta.url));
const statusline = defineStatusline({
description: "Show acme-db MCP usage state.",
render(ctx) {
const calls = ctx.usage?.calls ?? 0;
return `acme-db: ${calls} tool calls`;
},
});
const refreshIndex = defineAction({
id: "refresh-index",
description: "Refresh the local schema index.",
async run(ctx) {
return { message: `Refreshed schema index for ${ctx.host}` };
},
});
export default defineConnector({
server: { transport: "stdio", command: "node", args: [serverPath] },
statusline,
actions: [refreshIndex],
});4. Choose by user need#
| Need | Surface | Beginner rule |
|---|---|---|
| The model should call a capability | MCP tool | Keep validation in the server. |
| The host lifecycle should add policy/context | Hook | Test one host per hook paradigm; MCP-only hosts skip hooks. |
| The human needs a compact state signal | Statusline / HUD | Return short text; never block on network calls. |
| The human wants to trigger a command | Action | Use clear command names and surface errors to the user. |
| Users repeat the same instructions | Command, skill, subagent, or memory | Prefer static files for durable guidance; keep memory small. |
5. Verify after each added surface#
- Run install in one target host and read the generated diff or warning.
- Run doctor before adding the next surface.
- Confirm unsupported hosts skip with a warning instead of pretending the surface works.
- Keep hard safety in the MCP tool handler; hooks and actions are not a substitute for server validation.