Integrate Precept MCP into Your Code
Use the standard Model Context Protocol SDK to programmatically access Precept's B2B contact engine, search companies, and enrich target accounts from within your own applications.
Using the NPM Package
The Precept MCP server is published on NPM as @preceptai/mcp-server. You can connect to it programmatically using the official MCP TypeScript SDK.
Sign Up & Get Your Precept API Key
Before calling tools or bootstrapping an MCP client in code, you need an authenticated Precept API key:
- Create an account or log in at app.preceptai.co.uk.
- Navigate to the Developer Dashboard.
- Click Generate New API Key and copy your key.
Save this key into your project environment (e.g. .env file):
Install Dependencies
Install the official MCP TypeScript SDK, the Precept MCP server, and (optionally) the Anthropic SDK into your project.
Installing @preceptai/mcp-server locally is the recommended approach for production. It guarantees fast, deterministic startup with no network dependency. You can also use npx -y @preceptai/mcp-server for quick testing, but npx may check the registry on each run.
Call Tools Directly (Without AI)
If you just want to run queries programmatically from your backend, you can execute tools directly. This doesn't involve an LLM—it's just a standard function call over the MCP protocol. Use StdioClientTransport to spawn the server as a persistent child process, make your callTool() requests, and call client.close() when finished.
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
async function run() {
// Spawn the Precept MCP server as a child process (runs once, stays alive)
const transport = new StdioClientTransport({
command: "npx", // Quick start
args: ["-y", "@preceptai/mcp-server"],
// For production, install locally and use the direct path instead:
// command: "node",
// args: ["node_modules/@preceptai/mcp-server/dist/index.js"],
env: {
...process.env,
PRECEPT_API_KEY: "pt_your_api_key_here",
},
});
const client = new Client(
{ name: "my-app", version: "1.0.0" },
{ capabilities: {} }
);
await client.connect(transport);
try {
// Discover available tools
const { tools } = await client.listTools();
console.log("Available tools:", tools.map(t => t.name));
// Call as many tools as you need over this single connection
const result = await client.callTool({
name: "precept_search_companies",
arguments: { query: "Find AI companies in the UK that have at least 400 employees." },
});
console.log("Result:", result);
} finally {
// Always close to clean up the spawned process
await client.close();
}
}
run().catch(console.error);Or, Build an AI Agentic Loop
If you want an LLM to automatically decide when to search for companies or leads, you must build an agentic tool-use loop. You provide both your own local tools and the MCP tools to the model, and whenever it asks to use a tool, you route the execution to the correct handler and feed the result back to the model.
Note: The code below is a conceptual example showing how to route between your own local tools and the Precept MCP server using the Anthropic SDK (Claude).
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
import Anthropic from "@anthropic-ai/sdk";
const anthropic = new Anthropic();
// ── Customer's own tools (local tools already present in the app) ──
const customerTools = [
{
name: "check_inventory",
description: "Check product inventory in our warehouse",
input_schema: {
type: "object",
properties: { sku: { type: "string" } },
required: ["sku"],
},
},
];
// Customer's own tool execution logic
async function executeCustomerTool(name: string, args: any): Promise<string> {
if (name === "check_inventory") {
return JSON.stringify({ sku: args.sku, quantity: 42 });
}
return JSON.stringify({ error: "Unknown tool" });
}
// ── Precept MCP setup (runs ONCE at server startup) ─────────────
async function initPreceptMCP() {
const transport = new StdioClientTransport({
// For production with a locally installed package (npm install @preceptai/mcp-server):
command: "node",
args: ["node_modules/@preceptai/mcp-server/dist/index.js"],
//
// For quick testing without installation, you can use npx instead:
// command: "npx",
// args: ["-y", "@preceptai/mcp-server"],
env: { ...process.env, PRECEPT_API_KEY: process.env.PRECEPT_API_KEY },
});
const mcpClient = new Client(
{ name: "my-agent", version: "1.0.0" },
{ capabilities: {} }
);
await mcpClient.connect(transport);
return mcpClient;
}
// ── Agentic loop (runs per user message) ────────────────────────
async function runAgent(userPrompt: string) {
const mcpClient = await initPreceptMCP();
try {
// 1. Discover tools from Precept and map to Anthropic's format
const { tools } = await mcpClient.listTools();
const preceptTools = tools.map((t) => ({
name: t.name,
description: t.description ?? "",
input_schema: t.inputSchema as any,
}));
const preceptToolNames = new Set(tools.map((t) => t.name));
// Combine customer tools and Precept MCP tools
const allTools = [...customerTools, ...preceptTools];
// 2. Start the conversation
let messages: any[] = [{ role: "user", content: userPrompt }];
let response = await anthropic.messages.create({
model: "claude-3-5-sonnet-latest",
max_tokens: 4096,
tools: allTools,
messages,
});
// 3. Agentic loop — execute tools while the model requests them
while (response.stop_reason === "tool_use") {
const toolUseBlocks = response.content.filter(
(block) => block.type === "tool_use"
);
if (toolUseBlocks.length === 0) break;
// Append assistant's message to the conversation (including all tool_use blocks)
messages.push({ role: "assistant", content: response.content });
const toolResults = [];
for (const toolUseBlock of toolUseBlocks) {
let resultContent: string;
try {
if (preceptToolNames.has(toolUseBlock.name)) {
// Route to Precept MCP server
const mcpResult = await mcpClient.callTool({
name: toolUseBlock.name,
arguments: toolUseBlock.input as Record<string, unknown>
});
// Extract text content cleanly from MCP output
resultContent = mcpResult.content
.filter((c) => c.type === "text")
.map((c) => (c as any).text)
.join("\n") || JSON.stringify(mcpResult.content);
} else {
// Route to customer's own logic
resultContent = await executeCustomerTool(
toolUseBlock.name,
toolUseBlock.input
);
}
} catch (error: any) {
resultContent = JSON.stringify({ error: error.message || "Execution failed" });
}
toolResults.push({
type: "tool_result",
tool_use_id: toolUseBlock.id,
content: resultContent,
});
}
// 4. Feed the tool execution results back to the model
messages.push({
role: "user",
content: toolResults,
});
// 5. Get the next model response
response = await anthropic.messages.create({
model: "claude-3-5-sonnet-latest",
max_tokens: 4096,
tools: allTools,
messages,
});
}
const textBlock = response.content.find((b) => b.type === "text");
console.log("Final Answer:", textBlock?.text);
} finally {
// Always close the client to clean up the spawned MCP server
await mcpClient.close();
}
}
runAgent(
"Find verified contacts for Product Marketing leads at Stripe."
).catch(console.error);Updating the NPM Package
To ensure your agent workflows and local MCP runners have the latest tools and schema definitions, keep the @preceptai/mcp-server package updated:
Project Dependency
Update to the latest version in your Node.js project:
Global CLI Install
Update your globally installed server instance:
Available Tools
The Precept MCP server gives your agent 13 tools. Each one is labelled Read-only (only looks things up), Uses credits (spends Precept credits but changes nothing else), or Takes action (creates, changes or deletes something in your account, or acts on LinkedIn for you). Credit costs are starting prices. Options like phone numbers cost more; see pricing for full rates.
Lead discovery
precept_search_leadsUses creditsFinds people who match a description of your ideal customer, such as job title, industry, company size and location. Can also add AI insights, verified emails and phone numbers, or a filter for people who recently engaged with posts on a topic.
Credits: From 0.1 per lead
precept_get_leads_from_post_searchUses creditsFinds people who recently wrote LinkedIn posts on given keywords, in the past 24 hours, week or month. Each result includes the post they wrote.
Credits: From 5.1 per lead
precept_enrich_leadsUses creditsAdds detail to contacts you already have, identified by LinkedIn URL or name and company: verified email and phone, professional summary, likely problems and initiatives. Can also draft a personalised email or LinkedIn message.
Credits: From 1 per lead
Company intelligence
precept_search_companiesUses creditsFinds companies from a plain-language description, for example “SaaS companies in London with 50–200 employees”. Can add decision makers, tech stack, revenue, funding, headcount by department, and answers to your own questions about each company.
Credits: From 1 per company
precept_get_company_insightsUses creditsReturns the same insights for companies you name by website or LinkedIn URL.
Credits: From 1 per company
Monitoring
precept_job_posting_subscriptionsTakes actionCreates, views, updates, lists and deletes recurring checks (every 7–30 days) for new job postings at chosen companies or matching a description, and finds decision makers at the hiring companies.
Credits: 0.5 per new decision maker found
precept_lead_subscriptionsTakes actionCreates, views, updates, lists and deletes recurring checks on specific people, by LinkedIn URL, for job changes, title changes and new posts. Up to 150 people per organisation.
Credits: See pricing
LinkedIn outreach (requires the Precept Chrome extension)
precept_campaign_queueTakes actionQueues LinkedIn connection campaigns to a list of leads, and shows, pauses, resumes, archives or removes them. Campaigns run one at a time, through the Precept extension in your own Chrome browser.
Credits: See pricing
precept_linkedin_messagesTakes actionSends one LinkedIn message (or a connection note if you aren't connected yet) to one person from your LinkedIn account, and checks whether it was delivered.
Credits: See pricing
precept_get_extension_statusRead-onlyChecks whether the Precept Chrome extension is installed and active, and which version is running.
Credits: None
Account and jobs
precept_check_creditsRead-onlyShows your remaining Precept credit balance.
Credits: None
precept_get_job_statusRead-onlySearches and enrichments run in the background. This checks a job's progress and returns its results when it finishes.
Credits: None
precept_check_versionRead-onlyChecks whether your connection is using the latest version of the Precept server.
Credits: None
Data & Permissions
What your agent can see and do once Precept is connected, what Precept receives, and how to disconnect.
What your agent can access
- Your agent acts as the Precept account whose API key you used to connect. With an organisation key, it uses that organisation’s credits and data.
- It can read your credit balance, search and enrichment results, subscriptions, campaign queue and message delivery status.
- Lead and company results come from Precept’s database of business profiles and public company information. They don’t come from your private LinkedIn data.
What your agent can do for you
- Spend Precept credits on searches and enrichments.
- Create, change and delete job-posting and lead subscriptions.
- Save lead lists to your Precept dashboard, and queue, pause or archive LinkedIn campaigns.
- Send LinkedIn messages and connection requests from your LinkedIn account. This only works if you’ve installed the Precept Chrome extension and are signed in to LinkedIn in Chrome.
- Send results to a webhook URL, but only if you give one.
What Precept receives
- Only what your agent puts in each tool call, such as search descriptions, LinkedIn URLs, company websites and message text.
- Precept doesn’t receive your conversation history, files, or data from your other tools.
- Precept stores searches, results, subscriptions and campaigns in your Precept account, as described in our privacy policy.
How sign-in works
- The
@preceptai/mcp-serverpackage runs on your own machine. It reads your API key from thePRECEPT_API_KEYenvironment variable. - It sends the key only to Precept’s API (
api.preceptai.co.uk), over HTTPS, as a Bearer token. - Keep the key out of source control. Use an environment variable or a secrets manager rather than writing it into shared config files.
Staying in control
Your code decides which tools the model can call. For unattended agents, consider leaving out the Takes action tools (messaging, campaigns and subscriptions), or requiring a human to approve them. Check your balance at any time with precept_check_credits.
Disconnecting
- Remove the Precept server from your MCP client config and stop any running agent processes.
- To cancel all existing access straight away, regenerate your API key on the Precept developer page. Anything using the old key stops working.
- To stop all LinkedIn activity, remove the Precept Chrome extension or archive your campaigns.