basic-mcp-server

basic-mcp-server

Provides arithmetic addition, string reversal, server info resource, and greeting prompts via Model Context Protocol over Streamable HTTP.

Category
访问服务器

README

ai-news-mcp

A Model Context Protocol server that answers questions about an AI news corpus, served over Streamable HTTP.

It is the data backend for an AI news agent: the agent asks questions, these tools search and read news.articles in Supabase Postgres.

Every tool is read-only. See Read-only guarantee.

Stateless: each request gets its own MCP server instance, nothing is kept between requests, so no session IDs and no sticky routing. The database pool is shared.

The corpus

news.articles, in a Supabase Postgres. As of 2026-08-24:

Articles 1083
Date range 2026-04-01 → 2026-08-24
Language French
Distinct categories 668
Distinct tags 927

Two properties drive the tool design:

  • Categories are free-text and fragmented — 668 distinct values across 1083 articles, with near-duplicates like Cybersécurité, Cybersécurité des agents IA and Cybersécurité et agents IA. Exact category matching is close to useless, so search_news matches categories as a case-insensitive substring.
  • views is NULL for every row. There is deliberately no "most read" tool; it would return noise.

What it exposes

Kind Name Description
Tool search_news Search by free text, category, tags and date range; paged
Tool get_article One article in full, by id or article_url
Tool list_categories Distinct categories with counts, for discovery
Tool list_tags Distinct tags or key_words with counts
Tool news_stats Coverage: totals, date range, volume per month, leading themes
Resource news://overview Corpus size, date range and top tags as JSON
Prompt ai_news_analyst Grounds an answer in the corpus, with citations

search_news returns summaries truncated to 320 characters — full summaries fill a model's context fast. Call get_article for the complete text of one article.

Files

  • index.js — HTTP(S) host: routing, auth check, TLS, lifecycle
  • mcp-server.js — the MCP server: tools, resource, prompt
  • db.js — Postgres pool and the read-only query helper
  • auth.js — bearer token verification
  • inspect-cli.js — dev helper; runs the MCP Inspector CLI against this server

Run

npm install
cp .env.example .env     # then set DATABASE_URL
npm start
# ai-news-mcp listening on http://0.0.0.0:8080/mcp

DATABASE_URL is required — the server exits with instructions if it is missing. Use the Supabase transaction pooler string (port 6543): dashboard → Connect → Transaction pooler.

Read-only guarantee

The MCP endpoint may be exposed without authentication, so "our SQL only does SELECTs" is not a strong enough guarantee. Two independent layers:

  1. No tool accepts SQL. All five run fixed statements; caller input only ever arrives as bound parameters, and the one interpolated identifier (tags vs key_words in list_tags) is constrained by a Zod enum before it is used.
  2. Postgres refuses writes. Every query runs inside BEGIN READ ONLY with a SET LOCAL statement_timeout (db.js). SET LOCAL rather than a session-level SET because under transaction pooling a session setting would leak to whichever client is handed that backend next.

Verified against the live database:

INSERT  blocked: cannot execute INSERT in a read-only transaction
UPDATE  blocked: cannot execute UPDATE in a read-only transaction
DELETE  blocked: cannot execute DELETE in a read-only transaction
DDL     blocked: cannot execute CREATE TABLE in a read-only transaction
SELECT  still works: 1083 rows

For defence in depth, point DATABASE_URL at a dedicated read-only role rather than the owner:

CREATE ROLE mcp_reader LOGIN PASSWORD '...';
GRANT USAGE ON SCHEMA news TO mcp_reader;
GRANT SELECT ON news.articles TO mcp_reader;

Then a bug in this server cannot write even if the transaction guard were removed.

Authentication

Off unless MCP_AUTH_TOKEN is set. Set it. Every tool reads your database, so an open endpoint lets anyone who finds the URL query the corpus and burn your Supabase quota. The startup banner warns when the token is missing.

npm run gen-token          # prints a random 32-byte hex token (64 chars)
MCP_AUTH_TOKEN=<token> npm start

With a token set, requests need Authorization: Bearer <token>. The scheme is case-insensitive; the token is not. Missing or bad credentials get 401 and a WWW-Authenticate challenge, compared in constant time (both sides SHA-256'd, then timingSafeEqual) so the token can't be recovered by timing the responses.

Tokens shorter than 32 characters trigger a startup warning — a token guarding a database should not be a memorable word. Use gen-token.

GET /health never requires a credential, so it works as a platform health check.

Verified behaviour:

Request Result
No Authorization header 401 + WWW-Authenticate: Bearer
Wrong token 401 + error="invalid_token"
Token without the Bearer prefix 401
Correct prefix of the real token 401
Correct token 200
GET /health, no credential 200

Configuration

Env var Default Purpose
DATABASE_URL — Required. Supabase Postgres connection string
DIRECT_URL — Fallback if DATABASE_URL is unset
MCP_AUTH_TOKEN — Unset ⇒ open to everyone; set ⇒ bearer token required
PORT 8080 Listen port
HOST 0.0.0.0 Bind address. Set 127.0.0.1 for local-only
MCP_PATH /mcp Endpoint path
PGPOOL_MAX 4 Pool size; keep small, poolers have connection limits
PG_STATEMENT_TIMEOUT_MS 8000 Per-query ceiling
PGSSL_STRICT — 1 verifies the server cert (needs the Supabase CA)
TLS_KEY / TLS_CERT — Paths to PEM files; both set ⇒ HTTPS

Try it with curl

curl -X POST http://127.0.0.1:8080/mcp \
  -H 'content-type: application/json' \
  -H 'accept: application/json, text/event-stream' \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"search_news","arguments":{"query":"Nvidia","limit":3}}}'

Add -H "authorization: Bearer $MCP_AUTH_TOKEN" if you set a token.

Try it in the Inspector

npm run inspect:cli -- --method tools/list
npm run inspect:cli -- --method tools/call --tool-name news_stats
npm run inspect:cli -- --method tools/call --tool-name search_news --tool-arg query=Anthropic
npm run inspect:cli -- --method resources/read --uri "news://overview"

The web UI (npm run inspect) needs Transport Streamable HTTP and URL http://127.0.0.1:8080/mcp. If you set a token, fill in Authentication → Header Name Authorization, value Bearer <token> — otherwise the Inspector sees the 401, assumes OAuth, and starts a discovery flow this server doesn't implement.

Connect it to an agent

claude mcp add --transport http ai-news https://ai-news-mcp.onrender.com/mcp

With a token, append --header "Authorization: Bearer <token>".

The ai_news_analyst prompt is the intended entry point for an agent: it tells the model to search before answering, to search in French regardless of the question's language, to cite article_url, and to say so plainly when the corpus has nothing rather than falling back on general knowledge.

Searching French text

Search uses Postgres full-text search with the french configuration, which handles stemming and stop words. It does not fold accents, because the unaccent extension is not installed on this database — energie will not match énergie.

To fix that, run once in the Supabase SQL editor and adjust FTS in mcp-server.js:

CREATE EXTENSION IF NOT EXISTS unaccent;

At 1083 rows every query is a fast sequential scan, so no index is needed yet. If the corpus grows past ~50k rows, add a GIN index on the to_tsvector expression.

Deploying

Currently live on Render. See DEPLOYMENT.md for that service's settings, redeploy steps and platform quirks.

Set DATABASE_URL — and ideally MCP_AUTH_TOKEN — in the host's environment settings. Never commit them; .gitignore covers .env and *.pem.

The server binds 0.0.0.0 and honours an injected PORT, which is what container platforms require. A process bound to 127.0.0.1 is unreachable from outside its container even though its logs look healthy.

Adding your own tool

In mcp-server.js, and route the query through the read-only helper:

import { query } from "./db.js";

server.registerTool(
  "my_tool",
  {
    title: "My tool",
    description: "What it does — the model reads this to decide when to call it.",
    inputSchema: { term: z.string() },
  },
  async ({ term }) => {
    const rows = await query("SELECT id, title FROM news.articles WHERE title ILIKE $1", [`%${term}%`]);
    return { content: [{ type: "text", text: JSON.stringify(rows, null, 2) }] };
  }
);

Never build SQL by concatenating caller input, and never add a tool that takes SQL as an argument — that would hand the corpus's read surface to whoever can reach the endpoint.

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选