{"_id":"callerkit-mcp","_rev":"5-2dd048005e6d81103be0fb0215ad4a2b","name":"callerkit-mcp","dist-tags":{"latest":"0.4.0"},"versions":{"0.0.0-stage":{"name":"callerkit-mcp","version":"0.0.0-stage","_id":"callerkit-mcp@0.0.0-stage","stub":true,"maintainers":[{"name":"callerkit","email":"callerkit2@gmail.com"}],"dist":{"shasum":"7cc540c213efca7c64e6753d5fd426c433cff3e5","tarball":"https://registry.npmjs.org/callerkit-mcp/-/callerkit-mcp-0.0.0-stage.tgz","fileCount":2,"integrity":"sha512-pbHJlte+/lzQ29BgQAzfHWKHMq68FYGMAp4aQF0aUSEQv/juvgjsJT1VUxiOVwD6iVdpHcJg/iMRZNoH3zcTOQ==","signatures":[{"sig":"MEQCIHLD2WS2wRXCw2ZOephJrOTFq8FIhd54uoCbl/h0sOtFAiA/mAMB9d3z0itQIpsvEM3/ZiYZNkHgxHvkSVaRQn85yg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":335},"_npmUser":{"name":"callerkit","email":"callerkit2@gmail.com"},"description":"Temporary package placeholder for staged publishing","directories":{}},"0.2.0":{"name":"callerkit-mcp","version":"0.2.0","keywords":["mcp","model-context-protocol","caller-id","phone-lookup","callerkit"],"license":"MIT","_id":"callerkit-mcp@0.2.0","maintainers":[{"name":"callerkit","email":"callerkit2@gmail.com"}],"homepage":"https://caller-kit.com/docs#mcp","bugs":{"url":"https://github.com/callerkit/caller-kit-backend/issues"},"bin":{"callerkit-mcp":"dist/index.js"},"dist":{"shasum":"8c74d5746512ffb77fc71abfe8b9802a80d474ef","tarball":"https://registry.npmjs.org/callerkit-mcp/-/callerkit-mcp-0.2.0.tgz","fileCount":13,"integrity":"sha512-bHduCHnxYtppHLlnjytYJswbroxA7T8qsi9Npui+siLK+K+fc3dsZt7vNJah5zHyMnRBaePUbAleTE+vOMRD4A==","signatures":[{"sig":"MEUCIQCSldDAFlOkhtLVtpAV+IRlH7kWIlhb9hI7NB54Wlly3QIgORVVUH7hLJssKRtu4BtGZ+Y5TEIn+mkTWj/fzaFLlB4=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIQCjGlyiPSOutVZ9rkzxlkTKzNDnXWm8x+PBHJelOvG5uwIgF3g+1iOW9tUmlPMsc8lZzGUMmBuahRHKcA/M+mt7RYk=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":42916},"main":"dist/index.js","type":"module","engines":{"node":">=18"},"gitHead":"cea19fa7635868b1e3f61974e240375760d6217d","scripts":{"test":"npm run build && node test/smoke.mjs","build":"tsc","start":"node dist/index.js","test:live":"npm run build && node test/live.mjs","start:http":"node dist/index.js --http","prepublishOnly":"npm test"},"_npmUser":{"name":"callerkit","email":"callerkit2@gmail.com"},"repository":{"url":"git+https://github.com/callerkit/caller-kit-backend.git","type":"git","directory":"mcp"},"_npmVersion":"11.19.0","description":"MCP server for the CallerKit caller ID / phone lookup API","directories":{},"_nodeVersion":"24.21.0","dependencies":{"zod":"^3.25.76","libphonenumber-js":"^1.13.15","@modelcontextprotocol/sdk":"^1.32.1"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^7.0.2","@types/node":"^26.6.5"},"_npmOperationalInternal":{"tmp":"tmp/callerkit-mcp_0.2.0_1791714291089_0.9344532291194358","host":"s3://npm-registry-packages-npm-production"}},"0.2.1":{"name":"callerkit-mcp","version":"0.2.1","keywords":["mcp","model-context-protocol","caller-id","phone-lookup","callerkit"],"license":"MIT","_id":"callerkit-mcp@0.2.1","maintainers":[{"name":"callerkit","email":"callerkit2@gmail.com"}],"homepage":"https://caller-kit.com/docs#mcp","bugs":{"url":"https://github.com/callerkit/caller-kit-backend/issues"},"bin":{"callerkit-mcp":"dist/index.js"},"dist":{"shasum":"ef13a08b4bcab7e2c2bfb0013a005854e8a15f8b","tarball":"https://registry.npmjs.org/callerkit-mcp/-/callerkit-mcp-0.2.1.tgz","fileCount":13,"integrity":"sha512-FUoFH+Jhqr6KsRpjXSVDDO7LfwQaDeF6uGRJ02GC+VQpsrqIyshaupq69rP1RQ1PInJ60Kg50ihPhpsSY8Ompg==","signatures":[{"sig":"MEQCIEnok7805oASly1pmW4jEOUtjmI/qw1U4DgchJJteL1GAiANVylzvB4HLPDZ1NqTotBAKB1Nymud0E+Sae6AMA+h4g==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIQDgs4jIHeee6KOAjW4RrVr3/Utmuh2DwpI8diZfpLWtHAIga/Mb/zxiYmO9tq1WzFjy3nTbxyNKQYgY8VuM2cCYehc=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":43493},"main":"dist/index.js","type":"module","engines":{"node":">=18"},"gitHead":"d02a282390a081290aaf2ce10e405c59da85d400","mcpName":"com.caller-kit/callerkit-mcp","scripts":{"test":"npm run build && node test/smoke.mjs","build":"tsc","start":"node dist/index.js","test:live":"npm run build && node test/live.mjs","start:http":"node dist/index.js --http","prepublishOnly":"npm test"},"_npmUser":{"name":"callerkit","email":"callerkit2@gmail.com"},"repository":{"url":"git+https://github.com/callerkit/caller-kit-backend.git","type":"git","directory":"mcp"},"_npmVersion":"11.19.0","description":"MCP server for the CallerKit caller ID / phone lookup API","directories":{},"_nodeVersion":"24.21.0","dependencies":{"zod":"^3.25.76","libphonenumber-js":"^1.13.15","@modelcontextprotocol/sdk":"^1.32.1"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^7.0.2","@types/node":"^26.6.5"},"_npmOperationalInternal":{"tmp":"tmp/callerkit-mcp_0.2.1_1791715068135_0.3445901428131988","host":"s3://npm-registry-packages-npm-production"}},"0.3.0":{"name":"callerkit-mcp","version":"0.3.0","keywords":["mcp","model-context-protocol","caller-id","phone-lookup","callerkit"],"license":"MIT","_id":"callerkit-mcp@0.3.0","maintainers":[{"name":"callerkit","email":"callerkit2@gmail.com"}],"homepage":"https://caller-kit.com/docs#mcp","bugs":{"url":"https://github.com/callerkit/caller-kit-backend/issues"},"bin":{"callerkit-mcp":"dist/index.js"},"dist":{"shasum":"5d459a8224ab7f74d143baf1b166c1ad730f67bf","tarball":"https://registry.npmjs.org/callerkit-mcp/-/callerkit-mcp-0.3.0.tgz","fileCount":25,"integrity":"sha512-O4EOBArP6eJCK+1/JaCl7HIl5axO2pvBE3Bq3Zjzj+m0PJCck0OPgAQGSvEqjXc8YKribpGelVIWV/svCoDidA==","signatures":[{"sig":"MEUCIQCZRW0XBOwXlbpkuDbgOHHlamBUblLr/J7HpGu4gs7XkgIgRzBZCVexpPooAhGrThnrYWVjzs9jJssw0zljF/oBYEU=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEYCIQC4tk/tQhe1cV94RBgQ9uJZLv7gfz3EJYLJ7YX3BB7x0QIhAKkbQh32hogEFJd+Jp73lD6uZ+D3dzDAHPr1YAAnkAGL","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":51795},"main":"dist/lib.js","type":"module","types":"dist/lib.d.ts","engines":{"node":">=18"},"exports":{".":{"types":"./dist/lib.d.ts","import":"./dist/lib.js"},"./package.json":"./package.json"},"gitHead":"a9c94126d64c60c0bfa9e058a70652b5bfa02f65","mcpName":"com.caller-kit/callerkit-mcp","scripts":{"test":"npm run build && node test/smoke.mjs","build":"tsc","start":"node dist/index.js","test:live":"npm run build && node test/live.mjs","start:http":"node dist/index.js --http","prepublishOnly":"npm test"},"_npmUser":{"name":"callerkit","email":"callerkit2@gmail.com"},"repository":{"url":"git+https://github.com/callerkit/caller-kit-backend.git","type":"git","directory":"mcp"},"_npmVersion":"11.19.0","description":"MCP server for the CallerKit caller ID / phone lookup API","directories":{},"_nodeVersion":"24.21.0","dependencies":{"zod":"^3.25.76","libphonenumber-js":"^1.13.15","@modelcontextprotocol/sdk":"^1.32.1"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^7.0.2","@types/node":"^26.6.5"},"_npmOperationalInternal":{"tmp":"tmp/callerkit-mcp_0.3.0_1791716407833_0.094282989169572","host":"s3://npm-registry-packages-npm-production"}},"0.4.0":{"_id":"callerkit-mcp@0.4.0","bin":{"callerkit-mcp":"dist/index.js"},"bugs":{"url":"https://github.com/callerkit/caller-kit-backend/issues"},"dist":{"shasum":"8fc2f4945e6009a91478a065b94ee6f65e0a4d5d","tarball":"https://registry.npmjs.org/callerkit-mcp/-/callerkit-mcp-0.4.0.tgz","fileCount":25,"integrity":"sha512-Oq5ZaLK3VQqLGz5BHUgce5W8BJ6EcshCU/TwGuTZKMm7AHpEs/hl5VxYtFR3dkYVQP4+M3Xt4Kh07A1IjhziuQ==","signatures":[{"sig":"MEQCIFgwlZPmWdp4SiVJzfb/PPVmwZsOEjEtOwonzl6vP3LjAiBQgWfYM6er56UPvl67tA7QJ6jh61pYM/bzq7qb09CQbA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQCzjL3Aa4AsGPoRZBggTIooYOakTWiN5y/JyjYHIPzSzQIhAIhnNIEk5kxvLNxTX63TQU1DymAdF1jTw+iefRfbGwF5"}],"unpackedSize":54412},"main":"dist/lib.js","name":"callerkit-mcp","type":"module","types":"dist/lib.d.ts","engines":{"node":">=18"},"exports":{".":{"types":"./dist/lib.d.ts","import":"./dist/lib.js"},"./package.json":"./package.json"},"gitHead":"7ecf4cfca90f684eed4fcffb5ce4a5c2dbb83eff","license":"MIT","mcpName":"com.caller-kit/callerkit-mcp","scripts":{"test":"npm run build && node test/smoke.mjs","build":"tsc","start":"node dist/index.js","test:live":"npm run build && node test/live.mjs","start:http":"node dist/index.js --http","prepublishOnly":"npm test"},"version":"0.4.0","_npmUser":{"name":"callerkit","email":"callerkit2@gmail.com"},"homepage":"https://caller-kit.com/docs#mcp","keywords":["mcp","model-context-protocol","caller-id","phone-lookup","callerkit"],"repository":{"url":"git+https://github.com/callerkit/caller-kit-backend.git","type":"git","directory":"mcp"},"_npmVersion":"11.19.1","description":"MCP server for the CallerKit caller ID / phone lookup API","directories":{},"maintainers":[{"name":"callerkit","email":"callerkit2@gmail.com"}],"_nodeVersion":"24.22.1","dependencies":{"zod":"^3.25.76","libphonenumber-js":"^1.13.15","@modelcontextprotocol/sdk":"^1.32.1"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^7.0.2","@types/node":"^26.6.5"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/callerkit-mcp_0.4.0_1792836023027_0.48043109228450054"}}},"time":{"created":"2026-10-11T10:23:35.284Z","modified":"2026-10-24T10:00:23.266Z","0.0.0-stage":"2026-10-11T10:23:35.284Z","0.2.0":"2026-10-11T10:24:51.171Z","0.2.1":"2026-10-11T10:37:48.209Z","0.3.0":"2026-10-11T11:00:07.914Z","0.4.0":"2026-10-24T10:00:23.115Z"},"bugs":{"url":"https://github.com/callerkit/caller-kit-backend/issues"},"license":"MIT","homepage":"https://caller-kit.com/docs#mcp","keywords":["mcp","model-context-protocol","caller-id","phone-lookup","callerkit"],"repository":{"url":"git+https://github.com/callerkit/caller-kit-backend.git","type":"git","directory":"mcp"},"description":"MCP server for the CallerKit caller ID / phone lookup API","maintainers":[{"name":"callerkit","email":"callerkit2@gmail.com"}],"readme":"# callerkit-mcp\n\nAn [MCP](https://modelcontextprotocol.io) server that lets AI assistants and agents (Claude, Cursor, custom agents) use the CallerKit caller-ID / phone-lookup API.\n\n## Tools\n\n| Tool | What it does | Cost |\n|---|---|---|\n| `callerkit_lookup_phone` | Name, aliases (with report counts), spam count, emails, socials, carrier, line type, country for one number | 1 credit if a name is found |\n| `callerkit_assess_number_risk` | 0-100 risk score + level + reasons; optional `expected_name` match (Latin and Arabic aware) | 1 credit if a name is found |\n| `callerkit_search_by_name` | Numbers matching a name in a country, paged (paid plan) | 1 credit / result |\n| `callerkit_search_by_email` | Details matching an email, max 10 (paid plan) | 1 credit / result |\n| `callerkit_bulk_lookup` | Up to `CALLERKIT_MAX_BULK` (default 25) numbers, deduped, compact rows with risk level | 1 credit / number found |\n\nAll tools are annotated read-only / idempotent. \"No record\" is always reported as `unknown`, never as \"safe\".\nNames, aliases, emails and social profiles come from other people's address books, so they are treated as\nuntrusted text: control, zero-width and bidi-override characters are stripped, whitespace collapsed and length\ncapped (`cleanText` in `src/normalize.ts`), and descriptions tell the model never to follow instructions in them.\nPhone numbers can be E.164 (`+971501234567`) or national with a `country` (`0501234567`, `AE`); the\nserver derives the `country_code` the API needs with libphonenumber.\n\n## API contract\n\nThis lives in the backend repo, and mirrors it in two files:\n\n- `src/endpoints.ts`: paths and request bodies (`routes/api.php`, `app/Http/Requests/Api/*Request.php`).\n- `src/normalize.ts`: the `{code, status, msg, data: {numbers: {data: [...]}}}` envelope and `NumberResource` rows.\n\nError mapping (`src/client.ts`): 401 bad key, 403 blocked / no plan / paid-only (with `upgrade_url`),\n422 validation, 429 **with** `Retry-After` = throttled (retried), 429 **without** = credits used up (not retried;\nbulk stops). Change these files together with the backend.\n\n## MCP Registry\n\nListed as `com.caller-kit/callerkit-mcp` ([server.json](server.json); `mcpName` in package.json must match).\nThe listing has two ways in: this npm package (stdio) and the hosted server `https://mcp.caller-kit.com/mcp`\n(`remotes`, from `../mcp-hosted`).\nNamespace ownership is proven by `public/.well-known/mcp-registry-auth` in the backend (HTTP auth, Ed25519).\nTo release: bump `version` in package.json, `src/version.ts` and both versions in server.json, `npm publish`,\nthen `mcp-publisher login http --domain caller-kit.com --private-key …` and `mcp-publisher publish`.\n\n## Library use\n\n`import { createCallerKitServer, loadConfig } from \"callerkit-mcp\"` gives an `McpServer` bound to one API key, to\nserve over any transport. The optional third argument `{ onAuthError }` is called when CallerKit rejects the key\n(401), so a host can ask the user to sign in again. The hosted server in `../mcp-hosted` uses this. The `callerkit-mcp` binary is the CLI.\n\n## Install and run\n\n```bash\nnpm install\nnpm run build\ncp .env.example .env     # then export the variables, or pass them in your client config\nnpm test                 # 26 end-to-end checks against a mock API, over stdio and HTTP\nnpm run test:live        # contract check against the real backend (default: local php artisan serve)\n```\n\nRequired: `CALLERKIT_API_KEY`. Optional: `CALLERKIT_BASE_URL` (default `https://caller-kit.com`; must be `https://`, except localhost).\n`CALLERKIT_INCLUDE_RAW=true` also returns the raw API response, for debugging.\n\n`test:live` uses the `LocalDevSeeder` key and sample numbers by default; override with `CALLERKIT_LIVE_URL`,\n`CALLERKIT_LIVE_KEY`, `CALLERKIT_LIVE_PHONE`. Name/email search need Sphinx, so they only run with\n`CALLERKIT_LIVE_SEARCH=1`. Against production it spends real credits.\n\n### Claude Desktop (stdio)\n\n```json\n{\n  \"mcpServers\": {\n    \"callerkit\": {\n      \"command\": \"node\",\n      \"args\": [\"/absolute/path/to/caller-kit-backend/mcp/dist/index.js\"],\n      \"env\": {\n        \"CALLERKIT_API_KEY\": \"…\",\n        \"CALLERKIT_BASE_URL\": \"https://…\"\n      }\n    }\n  }\n}\n```\n\n### Claude Code\n\n```bash\nclaude mcp add callerkit \\\n  --env CALLERKIT_API_KEY=… --env CALLERKIT_BASE_URL=https://… \\\n  -- node /absolute/path/to/caller-kit-backend/mcp/dist/index.js\n```\n\n### Remote (Streamable HTTP): for selling this to other developers\n\n```bash\nPORT=3000 HOST=127.0.0.1 node dist/index.js --http\n# POST http://127.0.0.1:3000/mcp   header: Api-key: <the CALLER'S own CallerKit key>\n```\n\nStateless, one server instance per request, and **every caller brings their own CallerKit key**, so the server holds no secrets and one customer can never spend another's credits. Put it behind TLS (Caddy/nginx/Cloudflare) and add rate limiting at the edge. It binds to loopback by default; only set `HOST=0.0.0.0` behind a proxy.\n\n## What building this taught (insights on building MCP servers)\n\n**1. Design tools around the agent's job, not around your endpoints.** CallerKit has three raw endpoints. The most useful tool, `assess_number_risk`, isn't an endpoint at all: it composes a lookup with a scoring heuristic and answers \"should I ship this order?\". Fewer, outcome-shaped tools beat a 1:1 API wrapper.\n\n**2. The description is the product.** The model decides whether and how to call a tool from its name, description and schema alone. Say what it returns, when to use it, what it costs, input format (`E.164`, with an example), and limits. Prefix names (`callerkit_…`) so they don't collide with other servers.\n\n**3. Errors are part of the conversation.** Return `isError: true` with a message the model can act on (\"not valid E.164, e.g. +971…\", \"Pro plan required\", \"config problem, retrying won't help\") instead of throwing. A thrown exception becomes an opaque protocol error.\n\n**4. In stdio mode, stdout belongs to the protocol.** A stray `console.log` corrupts the stream. Log to stderr only. Mask personal data in logs (phones are logged as `+971***67`).\n\n**5. Validate at the edge, be lenient where it helps.** Strict schema on the things that must be right (an email must be an email), but in bulk input I accept junk entries and report them as `invalid` rather than rejecting the whole batch. My own test caught me being too strict here.\n\n**6. Make cost and blast radius visible.** The API charges per result, and an agent can loop. So: credit cost is in every description, bulk is capped, duplicates are removed, and bulk stops early on auth/plan errors instead of burning requests (verified: ≤ concurrency requests go out after a bad key or exhausted credits).\n\n**7. Treat the agent as an untrusted caller of sensitive data.** This API returns personal data, and agents make bulk profiling easy. The descriptions state the legitimate-use boundary, name/email search is Pro-gated by your API, and bulk is capped. Consider adding your own audit log and per-key daily limits server-side.\n\n**8. Be honest in derived outputs.** The risk score is a transparent, deterministic heuristic with reasons, and \"no record\" yields `score: null, level: unknown`. Models over-trust confident-looking numbers, so don't let a missing record read as \"safe\".\n\n**9. Isolate the contract.** All API shapes sit in `endpoints.ts` and `normalize.ts`; the rest of the server is tested against a mock, and `test:live` checks the mock's assumptions against the real backend. The first version guessed the shapes and got the path, body, envelope, not-found and 429 semantics wrong, which only reading the backend revealed.\n\n**10. Test through a real MCP client, not just unit tests.** `npm test` spawns the built server and drives it with the SDK's client over stdio and HTTP. That caught a logging bug (metadata overwrote the log level) and the over-strict bulk schema, neither of which unit tests of the pure functions would have shown.\n\n**Transport choice:** stdio for local tools (Claude Desktop / Code), Streamable HTTP for anything you host. Prefer stateless HTTP unless you truly need server-initiated messages or per-session state.\n\n## Next steps toward revenue\n\n- Publish to npm (`npx callerkit-mcp`) and list on MCP registries/directories, since discovery is the main channel.\n- Add a $19-39 CallerKit tier and pay-as-you-go credits (today the jump from 10 free requests to $119 is steep), and ship a real bulk endpoint so the client-side bulk can call it.\n- Hosted remote endpoint with per-key usage dashboards reuses your existing API-key system.\n","readmeFilename":"README.md"}