The agent ships with 21 built-in OAuth integrations. They cover most everyday and work tools. They do not cover everything. Custom MCP is the answer to "I have a niche tool we depend on; how do I make my agent able to use it?" The mechanism is a small server you write (or copy from a template) that exposes your tool to the agent via the Model Context Protocol.
This post is how to write one, what to put in it, what to skip, and what we have seen our most ambitious users build.
When to write a custom MCP
Three real cases.
You have an internal tool. Your company has a custom CRM or operations dashboard. The agent should be able to read from it and write to it. Build a small MCP server that wraps your internal API; the agent now has those tools.
You have a third-party tool we did not integrate. A niche industry tool (lab management, freight ops, regulatory filing). The tool has an API; you wrap it; the agent has the integration without us having to build it generically.
You want a tool we will not build. Some tools (high-frequency-trading APIs, regulated-industry-specific tools) are not on our roadmap because they are not generally applicable. Custom MCP lets you have them anyway.
The minimum viable MCP
A representative server. The full code is ~80 lines.
import { Server } from '@modelcontextprotocol/sdk/server';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio';
const server = new Server(
{ name: 'my-tools', version: '0.1.0' },
{ capabilities: { tools: {} } }
);
// Define a tool
server.tool('lookup_customer', {
description: 'Look up a customer in our CRM by email.',
parameters: {
type: 'object',
properties: {
email: { type: 'string' }
},
required: ['email']
}
}, async ({ email }) => {
const customer = await fetch(
`https://your-crm.com/api/customers?email=${email}`,
{ headers: { 'Authorization': `Bearer ${process.env.CRM_TOKEN}` }}
).then(r => r.json());
return { content: [{ type: 'text', text: JSON.stringify(customer) }] };
});
// Define another tool
server.tool('create_invoice', {
description: 'Create a new invoice in our billing system.',
parameters: {
type: 'object',
properties: {
customer_id: { type: 'string' },
amount: { type: 'number' },
description: { type: 'string' }
},
required: ['customer_id', 'amount']
}
}, async ({ customer_id, amount, description }) => {
const invoice = await fetch('https://your-billing.com/api/invoices', {
method: 'POST',
headers: { 'Authorization': `Bearer ${process.env.BILLING_TOKEN}` },
body: JSON.stringify({ customer_id, amount, description })
}).then(r => r.json());
return { content: [{ type: 'text', text: `Invoice ${invoice.id} created.` }] };
});
const transport = new StdioServerTransport();
await server.connect(transport);That is the entire surface. Run it once locally to test, deploy it (Cloudflare Workers, Vercel, your own VPS), and connect the URL to your Ajeris account. The agent picks up the new tools.

What to put in your tools
Three principles from designing the built-in tools.
Verb-object names. lookup_customer, not customer_get_by_email. The model parses verb-object more reliably than the alternatives.
Parameter names that match natural language. If users ask "look up John's contact," your tool's parameter should be name not firstNameOrFullNameOrEmail. The agent works back from the user's phrasing to the tool call; obvious parameter names help.
Honest descriptions. Tools fail when the description over-claims. "Books a meeting" is not the same as "drafts a meeting invite for user approval." Be specific in the description; the agent uses it to decide when to invoke.
What to skip
Three things we have seen people put in custom MCP that they should not.
Auth flows. Do not implement an OAuth flow inside your MCP. Use a static token (per-user) injected at MCP-connect time. Auth flows are infrastructure, not tools.
Long-running processes. Tools should return in seconds. If the underlying operation is long (a 10-minute report generation), the tool should kick off the work and return a job ID; a separate tool checks status.
Multi-step state. Tools should be stateless from the agent's perspective. If your tool needs state ("user is in the middle of a multi-step flow"), persist that state on your server side and reflect it in the next tool call's parameters.
Connecting the MCP to your Ajeris account
The flow is one form-fill on the manage page or one sentence to the agent.
You: connect a custom MCP at https://my-tools.example.com/mcp
bearer token [your-token]
Ajeris: Validating the MCP server.
Detected 4 tools: lookup_customer, create_invoice,
send_message, list_open_jobs.
Connect? [yes/no]
You: yes
Ajeris: Connected. Tools are live now. Ask away.The agent validates the server (the MCP must respond to the standard initialization handshake) and lists the tools it found. You confirm; the connection is live. The agent uses the new tools the next time you ask for something they fit.
- 1Write the server50-200 lines. Tools, descriptions, parameters.
- 2DeployCloudflare Worker, Vercel function, or your VPS.
- 3Connect to AjerisPaste URL + bearer in the manage page.
- 4UseAgent uses the new tools on the next turn.
- 5IterateUpdate the server; reconnect to refresh tool definitions.
What our most ambitious users have built
A few representative shapes that fit naturally.
A small marina. Wrap a slip-management system as an MCP. The agent now answers "is slip 14 available next weekend" and books slips through the MCP.
A specialty pharmacy. Wrap an inventory system. The agent answers do you have <medication-name> in stock and queues call-backs when restocked.
A travel agency. Wrap a fare-search tool. The agent answers "what's the cheapest way to get from ATL to SFO Friday."
A property manager. Wrap a tenant-service-request system. The agent triages, schedules, and dispatches without the property manager seeing a ticket.
In each case the underlying business already has the API; the MCP is a thin wrapper that exposes the API to the agent. The work is hours, not weeks.
- Wait for us to build an integration for your specific tool.
- Build a workaround using webhooks or zaps.
- Manually copy data between your tool and the agent.
- Live with the agent not knowing your most-used internal tool.
- Wrap your tool in 50-200 lines.
- Deploy on infrastructure you already use.
- Agent reads and writes to your tool natively.
- Tool is fully integrated within an afternoon of work.
Frequently asked
Is the protocol open?
What languages can I write the server in?
Where should I host the MCP?
Can the MCP read user data from Ajeris?
What if my MCP goes down?
Try it
If you have an internal tool you wish the agent knew about, write the MCP today. The first hour you save (or the first booking that books because the agent had access to your scheduling system) pays back the afternoon of work.


