finance-mcp-server
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@finance-mcp-serverwhoami"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Fintools
A containerized Model Context Protocol (MCP) server with a management dashboard.
Users sign in with Google, manage their own access tokens and OAuth 2.1 clients;
admins manage users. The MCP endpoint (Streamable HTTP at /mcp) accepts both
personal access tokens and OAuth 2.1 access tokens issued by the built-in
authorization server.
Stack: Hono · Vite · React 19 · React Router · TanStack Query · Tailwind CSS 4 · Drizzle ORM · PostgreSQL · TypeScript. One process serves everything — in dev, Hono runs inside the Vite dev server; in production, Hono serves the built SPA.
Documentation: https://shinchven.github.io/finance-mcp-server/ — built from
docs-site/ with VitePress and deployed to GitHub Pages on every
push to main.
Features
Google sign-in only — no passwords. Access is invitation-only: admins invite users by email;
ADMIN_EMAILSseeds admin accounts at boot.Personal access tokens — optional expiry, enable/disable, revoke/delete, copy-once display, last-access tracking. Only SHA-256 hashes are stored.
OAuth 2.1 authorization server — PKCE (S256) required, dynamic client registration (RFC 7591), discovery metadata (RFC 8414/9728), refresh token rotation with reuse detection, revocation (RFC 7009), consent screen.
Fintools MCP endpoint — Streamable HTTP at
/mcpwith 10 read-only Yahoo Finance tools pluswhoami; requests use the same PAT/OAuth 2.1 authorization layer as the rest of the MCP service.Cross-market fund relationship layer — 6 further tools that answer which fund gives me exposure to this stock, sector or theme, using an offline-ingested index of disclosed fund holdings rather than keyword search over fund names. China public funds and US ETFs share one index, so asking who holds NVDA returns both, tagged with the market each fund trades in.
Notes with full-text search — a place the assistant writes down what a conversation established (a thesis, a decision, the reasoning behind it) and finds it again later. Notes carry a summary for scanning, tags, links to the symbols they are about, and optional collections; 6 MCP tools read and write them, and the Notes page browses and edits the same rows. Search is Postgres full text over a stored
tsvector, paired with substring matching so Chinese phrases and partial words match too.Connector Setup guides — in-dashboard, copy-ready setup guides for Claude, Claude Code, Codex, Cursor, VS Code, Antigravity 2, Gemini Spark and generic MCP clients, with both OAuth and personal-token instructions.
Admin — user management (invite/enable/disable/role), all registered OAuth clients, full audit log, and the fund cache console.
URL-driven UI — search, filters, pagination, sorting and tabs all live in URL search params, so every view is shareable and back/forward-safe.
Related MCP server: MCP Authentication Demo
Quick start (development)
Requirements: Node 22+, PostgreSQL.
cp .env.example .env # fill in DATABASE_URL, SESSION_SECRET, Google credentials, ADMIN_EMAILS
npm install
npm run dev # one process: http://localhost:5173 (follows PORT)Migrations run automatically at boot, and every ADMIN_EMAILS entry is seeded
as an active admin. Sign in with the matching Google account.
Google OAuth setup
Create an OAuth client (type "Web application") at
Google Cloud Console → Credentials
and add the redirect URI {APP_URL}/auth/google/callback
(e.g. http://localhost:5173/auth/google/callback for dev). Dev and production
share one port, so a single APP_URL and one registered redirect URI cover both.
Deployment (Docker)
cp .env.example .env # set SESSION_SECRET, Google credentials, ADMIN_EMAILS, APP_URL
docker compose up -d # build from source: app + PostgreSQL 17, persistent volumeOr run the published image instead of building it:
docker compose -f docker-compose.ghcr.yml pull
docker compose -f docker-compose.ghcr.yml up -ddocker-compose.ghcr.yml defaults to
ghcr.io/shinchven/finance-mcp-server:latest, which tracks main; pin a release
with APP_IMAGE=ghcr.io/shinchven/finance-mcp-server:0.1.0 in .env. CI builds
multi-arch (linux/amd64, linux/arm64) images on every push to main and
publishes SemVer tags plus a GitHub Release for every v* tag — see
.github/workflows/docker.yml.
The image is a multi-stage build (node:24-alpine, non-root, healthcheck on
/healthz). The server waits for Postgres and applies migrations before
listening. Set APP_URL to the public HTTPS URL — it is the OAuth issuer.
Connecting an MCP client
The MCP endpoint is {APP_URL}/mcp (Streamable HTTP).
After signing in, open /connector-setup for client-specific commands,
configuration files, authentication steps and troubleshooting.
OAuth 2.1 (recommended): point the client at the URL; it discovers the authorization server via
/.well-known/oauth-protected-resource, registers itself, and sends you to the consent screen. Manage/revoke access on the OAuth Clients page.Personal access token: create one on the Access Tokens page and send it as
Authorization: Bearer mcp_….
Available MCP tools
Tool | Purpose |
| Find symbols, companies and related news |
| Recent headlines for a company, symbol or topic, newest first |
| Current or near-current quotes for up to 50 symbols |
| Selected company, price, ownership, filing and fund modules |
| Historical/intraday OHLCV data and market events |
| Predefined screens such as gainers, losers and most active |
| Region-specific trending instruments |
| Option expiration dates and call/put chains |
| Analyst research, developments and technical outlooks |
| Related and similar instruments |
| Financial statement data over time |
| Beats/misses, estimate revisions and the next report date, in one call |
| The crypto universe by market cap, with the Yahoo symbol for each asset |
earningsAnalysis stitches together four quoteSummary modules and does the
arithmetic, so answering "did they beat, and are estimates moving up or down"
takes one call instead of four plus manual work. It reports estimate
revisions, not just a current snapshot — a single estimate says nothing about
direction.
Crypto needs no separate price tools: Yahoo quotes and charts pair symbols like
BTC-USD through quote and chart. What it does not publish is a directory,
so cryptoTickers fills that one gap — it lists the universe by market cap from
CoinGecko's public tier and hands back the Yahoo symbol for each asset to chain
into the tools above. No API key: COINGECKO_API_KEY is optional and only
raises the rate limit.
Yahoo covers CN and HK listings through symbol suffixes (600519.SS,
0700.HK), so the tools above already span the A-share, Hong Kong and US
markets. What Yahoo does not carry is the inside of a fund: it publishes a
top-ten list for US ETFs and nothing at all for China's domestic public funds,
and it has no way to ask the question backwards. That is what the tools below
are for.
SEC EDGAR tools
For US issuers, EDGAR is the source of record that Yahoo mirrors — late, partially, and without provenance. These tools read it directly.
Tool | Purpose |
| An issuer's filing index, newest first, with direct document URLs |
| As-reported XBRL financials as a time series, with the filing behind every value |
Reach for these over the Yahoo statement tools when you need as-reported rather
than vendor-normalised figures, restatement-accurate history, or a citable
filing URL. secFinancials deduplicates each period to its latest restatement
and carries the us-gaap concept and accession number for every value.
Coverage is SEC registrants only: non-US listings and most ADRs have no CIK, and
filers predating XBRL have no company facts. Both tools say so explicitly rather
than returning an empty result. EDGAR requires a contact address in the
User-Agent on every request — set SEC_EDGAR_CONTACT_EMAIL.
Fund relationship tools
Tool | Purpose |
| Break a fund into sector/market exposure, with coverage and holdings stability |
| Reverse index — which funds hold a given stock, ranked by weight |
| Funds ranked by measured exposure to a sector or theme |
| Funds ranked by weight in positions matching symbol / sector / country / market-cap criteria |
| Substitutes for a fund, by cosine similarity of exposure vectors |
| Theme → tracking index / sector exposure / market exposure, in one call |
| Fees, size, top sectors and pairwise portfolio overlap for 2-10 funds |
| Cumulative/annualized return, max drawdown and volatility from NAV history |
Query-shape tests. The repo's SQL typechecks whatever it emits, and the tool tests mock the repo away, so a statement Postgres rejects at parse time can pass the whole suite — one did, and
fundsByStockfailed on every call in production while CI was green.repo-sql.test.tspins the shape offline;npm run test:db(withDATABASE_URLset) executes every repo query with every filter combination against a real database, inside a transaction that is always rolled back. It is skipped whenDATABASE_URLis unset.
fundsByHoldings is the tool that federated data makes possible: it goes back
to the raw positions and joins them against the enriched instrument table, so
criteria that were never precomputed — company size, country, an explicit basket
of symbols — can be combined in one query. Rank its results by
shareOfDisclosedPercent rather than matchedWeightPercent; the latter is a
share of net assets and is structurally smaller for a fund that discloses only
its largest positions.
Two numbers accompany every holdings-derived answer, and both matter:
coverage — the share of a fund's disclosed weight that could be classified. A 60% sector weight at 0.3 coverage is a much weaker claim than the same weight at 0.95.
holdings stability — how much of the previous report the fund still holds. Index funds sit near 1.0; a low score means last quarter's portfolio no longer describes the fund and its inferred exposure should be discounted.
themeToFunds reports index-tracking matches separately from holdings-derived
ones because a declared mandate does not drift, while a holdings snapshot can.
The mandate itself (跟踪标的) comes from the fund profile page and is only
populated from that field — never from 业绩比较基准, which for an active fund
is a blended benchmark and would make every active fund look like an index fund.
fundPerformance measures from cumulative NAV (累计净值) whenever the series
has it, so distributions are not read as losses — over a multi-year horizon that
difference compounds into a materially wrong number. The response states which
basis was used.
Watchlist tools
The only tools that write. They read and edit the authenticated user's own saved lists — the same rows the Watchlists page shows, so an assistant and the dashboard are never looking at different things.
Tool | Purpose |
| The user's lists, with item counts — the cheap "what exists" call |
| One list, priced: live quotes, fund NAV, notes, targets and a breadth summary |
| Add instruments or funds, with a note saying why |
| Drop items by symbol or fund code |
A list holds both kinds of thing at once: Yahoo symbols and 6-digit China fund
codes. A bare 6-digit ref is read as a fund code, since Yahoo's CN listings
always carry an exchange suffix (600519.SS), and kind overrides the guess.
Three deliberate limits on what an agent can do:
It cannot delete a list. Removing one item is a small correction; discarding a list throws away accumulated notes and targets. That lives on the dashboard, behind a confirmation.
It will not fork a list from a near-miss name. With lists already in place, an unrecognised name is an error listing the real ones unless
create: trueis passed — otherwise a single typo silently starts a parallel list, and the split only surfaces later. A user with no lists at all gets their first one made automatically; there is nothing to confuse it with.It will not guess between several lists. With more than one and no name given, the call fails and names the candidates.
Items store no prices. Values are fetched per request — Yahoo for instruments,
the local fund cache for funds — and the two are labelled basis: "market" and
basis: "nav" rather than blended: an intraday quote and a once-daily net asset
value are not the same measurement. Anything that could not be priced comes
back with available: false and a reason, so one bad symbol never costs you the
rest of the list. The summary weights every item equally; a watchlist records no
position sizes, so it cannot express a portfolio return.
Note tools
The assistant's long-term memory, and the other half of the Notes page. Six tools, because storing and finding are different jobs:
Tool | Purpose |
| Collections, tag vocabulary and tagged symbols with counts — the orientation call |
| Search and browse: full text, tags, symbols, collection, status, dates |
| Full bodies for up to 5 notes, by id |
| Save what a conversation established |
| Edit, append to, re-tag, file or archive one |
| Remove one note permanently |
The summary is the load-bearing field. notesSearch returns titles,
summaries and a snippet — never bodies — so an agent can scan fifty notes for
the two that matter and spend its context on those, via noteRead. The tool
descriptions ask for a summary on every write for exactly that reason.
Searching works in both languages. Bodies are indexed as a generated
tsvector (weighted title > summary > body, simple configuration) and matched
with websearch_to_tsquery, OR-ed with a substring match over title, summary,
body, tags and symbols. The vector finds whole words anywhere in a long body and
is GIN-indexed; the substring branch is what finds 降息 inside a Chinese
sentence, which no stock text-search parser will tokenize apart, and what
catches a half-remembered partial word. Ranking is ts_rank_cd plus a bump for a
title or summary hit, since the substring branch scores zero on its own.
Filters compose, and the two composition rules differ on purpose. tags
narrows — a note must carry every tag listed — because adding a tag is how you
cut a result set down. symbols widens — a note matches any symbol listed —
because "notes about NVDA or AMD" is the question people actually ask; a note is
rarely about every ticker in a basket.
Symbols use the watchlist's own vocabulary: a bare 6-digit code is a China fund,
anything else a Yahoo symbol, uppercased. One spelling serves both features, so
a note about 000834 and a watchlist item for it agree.
Three deliberate limits, mirroring the watchlist rules:
An agent cannot delete a collection. That would unfile everything in it; it lives on the dashboard behind a confirmation. Deleting one note — a row it could equally have written — is allowed.
Archiving is the recommended default.
status: "archived"keeps a note searchable and out of the listing, and is reversible; deletion is not.It will not fork a collection from a near-miss name. An unrecognised name is an error listing the real ones unless
createCollection: trueis passed.
Nothing an agent writes is hidden from the person who owns it: the same rows are
listed, edited, filed and deleted on /notes.
Fetching a fund on demand
Naming a fund is request enough for its data. Opening an uncached fund in the
fund cache console, or calling fundExposure, fundPerformance or
similarFunds on one, fetches it there and then — three requests, a couple of seconds — instead
of returning an empty result and telling you to go run a batch job.
Four things keep that safe on a request path:
One shared client per provider. The throttle is per client instance, so an on-demand fetch holding its own while a category sync held another would quietly double the request rate. Everything fetches through one per upstream.
In-flight de-duplication. Ten agents asking about the same fund at once cause one fetch.
The existing watermarks. A fund synced before is never refetched here — the test is "has this ever synced", not "does the data look useful", so a fund with one NAV point or a thin portfolio does not re-fetch on every call.
A queue ceiling. Past 8 pending fetches, callers are refused with a clear message rather than silently enqueuing an hour of scraping.
Sector classification runs against a deadline rather than to completion, so a
first touch does not wait through a serial walk of every holding. Whatever it
misses shows up as lower coverage on the exposure rows, and the tool response
says so.
Fund data ingest
The relationship tools read local tables only — no tool call ever hits an upstream data source. Any signed-in user fills one fund at a time simply by opening it; an admin fills whole categories from the Batch sync tab of the Funds page, or from the CLI:
npm run build
npm run ingest -- --provider=eastmoney --scope=qdii --limit=200
npm run ingest -- --provider=ishares --scope=all
npm run ingest -- --provider=eastmoney --scope=index --dry-run # counts only
npm run ingest -- --provider=eastmoney --codes=162411,270042
npm run ingest -- --provider=ishares --codes=IVV --skip-universe
npm run ingest -- --provider=eastmoney --scope=qdii --force # ignore freshness
npm run ingest -- --provider=ishares --probe # diagnose a source--probe is the first thing to run when a provider caches nothing. It makes
the same four calls the ingest does — listing, profile, holdings, NAV — against
one fund, writes nothing, and prints what each returned or how it failed. The
pipeline is deliberately tolerant (a fund that fails is collected into a summary
so a run of thousands survives it), and that tolerance is what hides a blocked
endpoint or a changed response format; the probe removes it.
The job runs six steps: fund universe → per-fund profile detail → holdings → NAV history → instrument enrichment from Yahoo → recomputed exposure. The first four are the provider's; the last two are shared, which is what makes exposure vectors from different markets directly comparable.
Instrument enrichment is the join to everything else. One quoteSummary
call per instrument yields the GICS sector (which covers CN, HK and US listings
under one taxonomy) and the attributes that make a cross-source question
answerable in SQL — ISIN, country of domicile, exchange, market capitalization.
The step is watermark-driven on instruments.profile_synced_at with a 7-day
window, and the watermark is set even when Yahoo returns nothing, so an
uncovered symbol costs one request a week rather than one per run.
Market caps are stored twice: as reported, and converted to USD. The native column cannot be compared across markets — filtering "above 10 billion" over a mixed JPY/USD/CNY column ranks by currency, not by size — so every size filter uses the USD one. Rates come from Yahoo, fetched once per currency per run.
Providers. A provider is one upstream source, declared in
src/shared/funds.ts and implemented in src/server/funds/providers/:
Provider | Universe | Holdings | Cadence |
| China public funds, 6-digit codes | Quarterly report, top holdings only | re-checked weekly |
| iShares US ETFs, listing tickers | Full published portfolio | daily |
Each declares its own scopes and freshness windows, because they age
differently: re-fetching a China quarterly report every day is waste, and
caching an iShares file for a week serves stale positions as current. Adding a
third means implementing FundProvider and adding a descriptor — no change to
the pipeline, the tables, or the tools.
Disclosure conventions differ, and the tools say so. funds.holdings_completeness
records whether a fund's weights cover its whole book (full) or only its
largest positions (top_holdings). Tool responses carry a note derived from it,
and a result mixing both gets an explicit warning — ranking funds by a disclosed
sector weight across conventions measures reporting rules, not portfolios.
Freshness windows. Each fund carries a per-step watermark, and a run skips whatever is still current: profile detail for 30 days, holdings for 7, NAV for
The three differ because they age differently — a fund's profile barely moves, portfolios are disclosed quarterly (re-checked weekly so a new quarter lands within days of publication), and NAV changes every trading day. This is what makes a repeat run cheap;
--forceoverrides it.
Share classes are ingested per fund code. A fund's A/C/现汇/现钞 classes share a portfolio, so fetching holdings once per class is redundant — but deduplicating means inferring the grouping from the fund name, and there is no share-class identifier in the upstream payload. A wrong grouping writes one fund's holdings under another's code, and nothing surfaces it. Since NAV and fees genuinely differ per class and must be fetched per code anyway, the deduplication would only save about 14% of a run's requests. Correct by construction beat it.
Per-fund failures are collected rather than fatal: the summary lists them and
the process exits non-zero, while everything that succeeded is still committed.
The last failure is also written to funds.last_sync_error so the dashboard can
show which funds are failing.
Unparseable holdings are counted, not swallowed. holdingsDropped in the
summary reports rows the parser could not read. A non-zero value means an
upstream format drift — the failure mode that once made Tokyo-coded positions
(285A) vanish from QDII portfolios with no error at all.
Notes page
/notes is the dashboard half of the note tools. Collections on the left with
their counts, the tag and symbol facets under them, results in the middle, and
one note open in a dialog with a markdown preview. Search text, collection, tag,
symbol, status, sort, page and the open note all live in URL search params, so a
filtered view — or a specific note — is a link.
Cards show the summary and, when a search matched further down, a snippet windowed around the hit. Bodies are fetched only for the note actually opened, which is the same split the MCP tools use. A note written by an assistant is marked as such, and deleting a collection keeps its notes: they fall back to unfiled rather than disappearing with the folder.
Funds page
/funds is open to every signed-in user: search by fund code, name, tracked
index or a stock the fund holds, filter by market and category, and click a
fund to open its stored portfolio. A fund nobody has opened yet is fetched on
the spot — a handful of throttled requests, de-duplicated server-side — so
reading the cache never depends on someone else having run a job first.
Batch sync is a second tab on the same page, and the only admin-restricted
part. The distinction is cost, not subject: opening one fund is seconds of
work for a fund already named, while a category run is hours of outbound
requests against hosts that rate limit, filling a cache every user shares, and
single-flight across the process — so one person starting one blocks everyone
else's. The tab shows what is actually cached (fund count, holdings rows,
distinct stocks, latest report date), the failing funds, and each provider's
index state. /api/sync/* and the cache statistics are admin-only server-side;
hiding the tab is a courtesy, not the check.
A sync is started per category. Picking one opens a confirmation showing
how many funds it matches, how many are already fresh, how many will actually be
fetched, the request count and an estimated duration — nothing is fetched until
that is confirmed. A run is tracked in ingest_jobs with live progress and can
be stopped; it is single-flight, since two concurrent runs would double the
request rate against hosts that already throttle.
Syncs run in the server process, so a restart interrupts one; jobs left running are marked failed at boot rather than appearing stuck forever.
Note on upstream formats. The Eastmoney and iShares endpoints are undocumented and their response shapes were implemented from their known structure, not verified against live responses. All shape knowledge is isolated in each provider's
parse.tsas pure functions with fixture-based tests, so a format change is a fixture-plus-parser fix that touches nothing else.
iShares holdings come from the product page's own API. The screener
(product-screener-v3.1.jsn) is unchanged and still lists the whole US lineup
in one request, but the per-fund holdings CSV at
…/<product page>/1467271812596.ajax?fileType=csv is retired: it now answers
with the product page's HTML — labelled text/csv, so the content type does not
give it away — or a 404, or a redirect to the closed-funds page. Holdings are
read from get-product-data (component=holdings.all, keyed by portfolio id)
instead, which is what the product page itself calls. Both planes are keyless;
the only requirement is a browser-like User-Agent, without which iShares
serves an interstitial page rather than data.
iShares can be blocked on the caller rather than the request. A browser-like
User-Agent is enough from most networks, but from a host whose egress IP
Akamai has already judged, the screener answers 403 from AkamaiGHost — the
CDN's own block page — and the request never reaches iShares. Setting ISHARES_PROXY_BASE
and ISHARES_PROXY_TOKEN routes those two requests, and only those two, through
the fintools-ishares-proxy
Cloudflare Worker; unset, they go direct. It is per-provider rather than a
process-wide HTTP_PROXY because eastmoney, SEC, Yahoo and CoinGecko all work
direct from the same host. --probe prints which route was taken, and a refusal
by the relay reports as the relay's, not as iShares bot protection. The relay
adds tens of milliseconds; what dominates either route is whether iShares' own
edge has the response. docs-site/operations/ishares-relay.md has the setup,
the measurements, and what a relay cannot fix.
When a source fails, it says so rather than reading as empty. The parsers
answer an unreadable payload with an empty list — right for a pure function, and
dangerous one layer up, where "no funds" is a statement no real provider makes.
So each fetch layer raises what its parser cannot: an HTML challenge page, a
screener that yields no products, a holdings download with no positions table. A
listing that returns nothing never records as a loaded index — it leaves the
error on fund_index_state and the previous watermark in place, so the next
attempt is immediate and the Batch sync tab shows the reason next to the
provider's counts. On-demand fetches report the same way: a fund whose upstream
failed comes back failed with the reason, not cached with an empty
portfolio.
The theme crosswalk in src/server/funds/crosswalk.ts is the one piece that
cannot be scraped — it maps a theme onto Eastmoney board names, Yahoo GICS
sectors and index names, which is what lets a single "半导体" query return both
onshore sector funds and QDII funds holding the same sector offshore. Extend it
by adding entries there.
| whoami | Current MCP user and authorization method |
Market data is provided through the unofficial yahoo-finance2 integration and
may be delayed, unavailable, changed, or removed for delisted symbols. Tool
responses are capped at 1 MB; narrow large requests by symbol count, date range,
or summary modules.
Scripts
Command | Purpose |
| Dev server (SPA + backend, single process) |
| Production build / run |
| Checks (run in CI) |
| End-to-end smoke test against a running dev server |
| Generate a migration after editing |
| The VitePress site in |
Architecture
See docs/PLAN.md for the full design and CLAUDE.md
for project conventions (notably: URL search params are the source of truth for
all page-level UI state).
The documentation site covers
deployment, configuration, every tool group and the fund pipeline in more depth;
its sources are in docs-site/.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.
No tool schema history has been recorded yet.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
MCP server for secureFlows: token-free URL builders and integration-linting tools for AI agents.
MCP server connecting AI agents to 100+ apps (Gmail, Slack, Notion, GitHub) via one-click OAuth.
MCP server for building and testing AI agents with multi-model experimentation and insights.
Hosted MCP server with managed OAuth for 15+ toolkits: Google Workspace, Fitbit, Oura, Kalshi, etc.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceMCP server with built-in Google OAuth 2.0 authentication, enabling secure tool access via Google sign-in with automatic token lifecycle management and optional domain restriction for Google Workspace organizations.MIT
- FlicenseNot gradedqualityDmaintenanceA production-ready MCP server with OAuth 2.1 authentication, enabling authenticated MCP tool calls via Google OAuth.-
- FlicenseNot gradedqualityBmaintenanceAn MCP server with HTTP/stdio support, a web admin panel for managing services, capabilities, and user permissions with Bearer token authentication, enabling relay and access control for MCP tools.-
- FlicenseNot gradedqualityCmaintenanceThis MCP server implements a secure OAuth 2.1 authorization server with Google login, enabling authenticated tool execution and a user interface for MCP applications.-
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/ShinChven/finance-mcp-server'
If you have feedback or need assistance with the MCP directory API, please join our Discord server