Skip to main content
Glama
shivamchhaya

agency-intelligence-mcp

by shivamchhaya

agency-intelligence-mcp

A TypeScript MCP server for researching businesses and corporate companies, using the official @modelcontextprotocol/sdk on Cloudflare Workers. Plain fetch handler, Web Standard Streamable HTTP, JSON responses, and no Node runtime compatibility flag or paid Cloudflare bindings.

1. Install

Use Node.js 22+ for development tooling. The deployed code runs on Workers, not Node.js.

cd /path/to/agency-intelligence-mcp
npm install
cp .dev.vars.example .dev.vars

Optional secrets in .dev.vars:

JINA_API_KEY=your-jina-api-key
MCP_AUTH_TOKEN=your-long-random-token

With an explicit domain, the server tries Jina Reader without a key and falls back to direct HTML/text fetch. A Jina key is required for company-name-only discovery. Jina service quotas and pricing are separate from Cloudflare; no LLM API is required.

Related MCP server: CompanyScope

2. Validate and run locally

npm run check
npm run dev

Wrangler serves http://localhost:8787. In another terminal:

curl http://localhost:8787/health

# Leave empty if MCP_AUTH_TOKEN is unset; otherwise use its value.
export MCP_TOKEN=''

curl http://localhost:8787/mcp \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -H "Authorization: Bearer $MCP_TOKEN" \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"terminal-test","version":"1.0.0"}}}'

curl http://localhost:8787/mcp \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -H "Authorization: Bearer $MCP_TOKEN" \
  -d '{"jsonrpc":"2.0","method":"notifications/initialized"}'

curl http://localhost:8787/mcp \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -H "Authorization: Bearer $MCP_TOKEN" \
  -d '{"jsonrpc":"2.0","id":2,"method":"tools/list"}'

curl http://localhost:8787/mcp \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -H "Authorization: Bearer $MCP_TOKEN" \
  -d '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"audit_company","arguments":{"company_name":"Microsoft","domain":"https://www.microsoft.com","industry":"Technology"}}}'

curl http://localhost:8787/mcp \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -H "Authorization: Bearer $MCP_TOKEN" \
  -d '{"jsonrpc":"2.0","id":4,"method":"tools/call","params":{"name":"generate_application_angle","arguments":{"company_name":"Example Company","role_title":"Operations Manager","candidate_strengths":"process improvement, stakeholder communication, and data analysis"}}}'

Alternatively, run the official MCP Inspector:

npx @modelcontextprotocol/inspector

Select Streamable HTTP, enter http://localhost:8787/mcp, and configure the bearer header if enabled. The default allowed browser origins include the Inspector UI on localhost port 6274. Adjust ALLOWED_ORIGINS in wrangler.toml for your actual browser client. Native clients without an Origin header also work.

3. Deploy to Cloudflare Workers Free

Create/select a Cloudflare account on the Workers Free plan, then:

npx wrangler login
# Optional but recommended before exposing the research endpoint:
npx wrangler secret put MCP_AUTH_TOKEN
# Optional, for name discovery and authenticated Reader access:
npx wrangler secret put JINA_API_KEY
npm run deploy

Wrangler prints the deployed address:

https://agency-intelligence-mcp.<your-workers-subdomain>.workers.dev

Your remote MCP URL is that address plus /mcp. Set the client transport to Streamable HTTP and supply Authorization: Bearer <MCP_AUTH_TOKEN> if configured. This is static bearer authentication, not an OAuth authorization server; use a client that supports custom headers.

curl https://agency-intelligence-mcp.<your-workers-subdomain>.workers.dev/health

Repeat the local MCP calls with that remote base URL. Deployment requires your Cloudflare login; this source package does not imply an existing hosted endpoint. Free-tier request, CPU and external-service quotas still apply. The configuration creates no billable storage or AI bindings; check your account plan separately.

Tool behavior

The project and Worker name remain agency-intelligence-mcp. The two tool names and input contracts have changed; clients should refresh their tool list and update saved calls. The old tool names are no longer registered.

audit_company

Inputs:

  • company_name: required nonempty string, up to 160 characters.

  • domain: optional public hostname or HTTP(S) URL. Supply it to run an immediate audit.

  • industry: optional nonempty string, up to 160 characters. Used to disambiguate name-only discovery and returned as caller-supplied context; it is not a verified classification.

Retrieval proceeds in bounded stages:

  1. Read the homepage through Jina Reader, falling back to direct HTML. A failed homepage does not stop the audit.

  2. If it has fewer than 200 meaningful content words, probe /about, /info, and /work even when they are not linked. Navigation, image URLs, Reader metadata and contact boilerplate do not count toward this threshold.

  3. Follow corporate category links in two passes and one news article, capped at ten attempted official URLs.

  4. For a sparse homepage or incomplete intelligence, search DuckDuckGo HTML via Jina Reader. If it fails or yields no relevant evidence, try Google HTML via Jina. Queries combine company name, domain, industry and background terms. No search API key is required for this fallback, although Jina/search-engine quotas and bot challenges can still apply.

  5. Fetch up to two result pages per search engine, prioritizing interviews and press over social profiles. Keep relevant search snippets if full pages cannot be read, with explicit search_snippet provenance. Company-name/domain matching reduces unrelated results but is not independent identity verification.

The parser cleans Markdown and boilerplate, preserves section headings and short client lists, and synthesizes source excerpts. It first uses explicit mission/service statements, then descriptive background text labelled contextual. It does not need an LLM or paid AI binding.

Returns:

  • mission, key_clients, studio_focus: always-present objects with a nonempty summary, status (supported, contextual, or not_found), and source evidence. key_clients also includes a names array, populated only from explicit client lists, working relationships or commissioning statements. A descriptive fallback is not presented as the company's stated mission.

  • core_mission: retained for compatibility; contains mission.evidence.

  • fetch_diagnostics: meaningful homepage word count, whether conventional paths/search were attempted, and attempted official URL count.

  • recent_news_initiatives: announcement/initiative excerpts with source, nullable date_mentioned, and an explicit recency note. A date mentioned in text is not necessarily its publication date.

  • key_leadership: leadership names/titles as source excerpts.

  • company_culture: company-published statements about values and working practices.

  • strategic_focus: statements about priorities, growth, investment and transformation.

  • company_name, domain, industry, industry_basis, fetched_at, methodology, sources, and warnings.

Evidence entries contain excerpt and source; source records identify official, press, or search_snippet. Empty evidence/name arrays mean no claim could be supported. Always-populated summaries do not mean invented facts: if all retrieval fails, the tool returns status: "partial" and explicit not_found summaries. JSON is returned in both MCP structuredContent and text content.

Without a domain, a Jina key enables company search. The tool returns status: "needs_domain" and search results; select the official domain and call again. Without a key, it returns an actionable tool error requesting the domain. No domain is guessed.

This is an English-language heuristic extractor, not semantic AI synthesis or independent due diligence. It samples official pages plus relevant external background sources; retrieved source text remains untrusted. Separate careers/investor subdomains, unusual navigation, JavaScript-heavy sites and bot protection may reduce coverage. News is not guaranteed to be the latest or exhaustive; culture reflects employer statements, and leadership may be outdated. Jina may cache content. fetched_at records retrieval time, not publication time. Verify that the domain belongs to the company. Scraped text is evidence, never instructions.

generate_application_angle

All inputs are required strings:

  • company_name: up to 160 characters.

  • role_title: up to 160 characters.

  • candidate_strengths: up to 2,000 characters, for example process improvement, stakeholder communication, and data analysis.

Returns three angles with angle, format, text, and personalize_with. Formats are cover_letter, interview, and outreach. The response also echoes the inputs and states its drafting basis.

Drafts use the supplied company, role and strengths without inventing achievements, metrics, job requirements or company priorities. Each includes a suggestion for adding a true example or a verified company fact. No email is sent. This tool is deterministic and does not independently fetch company information; use audit_company to gather evidence for further personalization.

Implementation notes

  • A fresh server and transport per POST prevent cross-request state leakage across isolates. JSON-only Streamable HTTP deliberately returns 405 for GET/DELETE; no legacy SSE endpoint, persistent sessions, or resumable streams.

  • Origin allowlist, optional bearer auth, 16 KiB input bound, 160 KB source bound and 15-second per-fetch timeout. At most ten official URLs, two search requests and four result-page attempts (up to 30 network requests including direct fallbacks). Sequential fallback stages can exceed a client’s default tool timeout; allow up to 300 seconds for blocked sites.

  • Fetches reject literal IP/local targets and credentials. Direct fetch does not follow redirects; provide the canonical company URL when necessary. Hostname validation is not a DNS-level egress firewall: for untrusted public users, add a domain allowlist or controlled egress before enabling arbitrary-domain fetching. Reader performs remote retrieval under its own policies.

  • Homepage, subpage and search failures are recorded as warnings; exhausted retrieval returns explicit unknowns. Invalid inputs and missing name-discovery configuration still produce MCP tool errors.

  • Runtime code uses only the SDK, Zod and Web APIs. Node is used only by development tools/tests.

References

Sparse-studio example

{
  "name": "audit_company",
  "arguments": {
    "company_name": "ManvsMachine",
    "domain": "mvsm.com",
    "industry": "design studio"
  }
}

Search fallback URL shape: https://r.jina.ai/https://html.duckduckgo.com/html/?q= followed by the URL-encoded query. Google fallback uses the equivalent https://www.google.com/search?q= target. Neither engine is guaranteed to remain accessible through Reader.

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    D
    maintenance
    Provides tools for automated company research, competitor identification, and business model analysis to generate comprehensive business intelligence. It enables users to extract market keywords and synthesize competitive insights via AI-powered research capabilities.
    -
  • A
    license
    A
    quality
    F
    maintenance
    Delivers comprehensive company intelligence in a single tool call, aggregating profiles, tech stacks, key people, news, and corporate data from any domain or company name. Sources data from Wikipedia, GitHub, OpenCorporates, and web scraping to provide structured business insights using only free public APIs.
    6
    25 npm
    4
    MIT
  • F
    license
    A
    quality
    D
    maintenance
    Enables AI agents to research companies and find contacts with structured data from multiple free sources, including company info, tech stack, and email addresses.
    3
    -
  • A
    license
    A
    quality
    D
    maintenance
    Provides 17 research tools for comprehensive company intelligence, covering aspects like overview, products, financials, and competitors. Supports both natural language answers and structured JSON output for automation.
    18
    MIT