bookmark-mcp
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., "@bookmark-mcpsave https://example.com with tag testing"
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.
bookmark-mcp — a production-ready MCP server showcase
A deliberately simple business case (a personal bookmark / reading-list manager) implemented the current standard way to build a Model Context Protocol server, so you can focus entirely on the technology:
TypeScript + the official
@modelcontextprotocol/sdk(high-levelMcpServerAPI)All three MCP primitives: tools, resources (static + templates), prompts
Local dev & testing on stdio / Node HTTP — production on Cloudflare Workers (Durable Object storage, deployed with one command)
Zod schemas as the single source of truth for validation, TypeScript types, and the JSON Schema shown to clients
Structured tool output (
outputSchema+structuredContent) and tool annotations (readOnlyHint,destructiveHint, …)Production patterns: pluggable storage adapters, stderr-only logging, atomic file writes, in-band error handling, origin validation, graceful shutdown, health endpoint
End-to-end tests with a real MCP client over the SDK's in-memory transport
src/
├── index.ts # entrypoint: stdio transport (local use with Claude Code/Desktop)
├── http.ts # entrypoint: Node Streamable HTTP (local/self-hosted, session-managed)
├── worker.ts # entrypoint: Cloudflare Worker + Durable Object ← PRODUCTION
├── server.ts # MCP layer: registers tools, resources, prompts (transport-agnostic)
├── store.ts # domain layer: BookmarkStore (runtime-agnostic, no node:* imports)
├── storage/
│ ├── file.ts # StorageAdapter: JSON file with atomic writes (Node only)
│ └── memory.ts # StorageAdapter: in-memory (tests)
├── schemas.ts # Zod schemas: validation + types + JSON Schema, all from one place
├── config.ts # env-var configuration (Node entrypoints)
├── logger.ts # structured logger (stderr on Node, log stream on Workers)
├── server.test.ts # end-to-end protocol tests (client ↔ server, in-memory)
└── store.test.ts # domain unit tests
wrangler.jsonc # Cloudflare deployment config (DO binding + migration)Why a bookmark manager?
The use case fits in one sentence — "save URLs, find them again, mark them read" — so every line of code is about how to build an MCP server, not about understanding a domain. Yet it is rich enough to exercise everything: create/read/update/delete actions, search filters, derived data (tag stats), duplicates and not-found errors, and persistence.
Related MCP server: linkding-mcp
Quick start
npm install
npm test # 15 end-to-end + unit tests
npm run dev # run on stdio (for MCP clients)
npm run dev:http # Node server on http://127.0.0.1:3000/mcp
npm run dev:worker # the PRODUCTION worker, locally in workerd (http://localhost:8787/mcp)
npm run inspect # open the MCP Inspector UI against this server
npm run deploy # ship to Cloudflare Workers (needs `npx wrangler login` once)Connect it to Claude Code
claude mcp add bookmarks -- npx tsx /absolute/path/to/playground_mcp/src/index.tsConnect it to Claude Desktop
{
"mcpServers": {
"bookmarks": {
"command": "npx",
"args": ["tsx", "/absolute/path/to/playground_mcp/src/index.ts"],
"env": { "BOOKMARKS_FILE": "/Users/you/bookmarks.json" }
}
}
}Then ask things like "bookmark https://example.com/article with tag testing", "what's unread in my reading list?", or invoke the reading_digest prompt.
Configuration
Env var | Default | Used by |
|
| both transports |
|
| both ( |
|
| HTTP only |
|
| HTTP only |
Architecture
Two design decisions make the "test locally, run on Cloudflare" split cheap:
The MCP layer is transport-agnostic.
createServer()builds the same server whether it is served over stdio, Node HTTP, the Workers transport, or an in-memory pipe in tests.The domain layer is runtime-agnostic.
store.tsuses only Web-standard APIs (nonode:*imports) and persists through a 2-methodStorageAdapterport. The file adapter is for laptops; the Durable Object adapter is production; the memory adapter is for tests.
flowchart LR
subgraph Clients
CD["Claude Desktop / Claude Code"]
IN["MCP Inspector"]
T["Vitest test client"]
end
subgraph Entrypoints
STDIO["index.ts<br/>stdio (local dev)"]
HTTP["http.ts<br/>Node Streamable HTTP"]
CF["worker.ts<br/>Cloudflare Worker + DO (production)"]
MEM["InMemoryTransport<br/>(tests)"]
end
subgraph Server["server.ts — createServer()"]
TOOLS["Tools<br/>add_bookmark · search_bookmarks<br/>mark_read · delete_bookmark"]
RES["Resources<br/>bookmarks://all · bookmarks://stats<br/>bookmarks://bookmark/{id}"]
PROMPTS["Prompts<br/>reading_digest"]
end
subgraph Domain["store.ts — BookmarkStore (runtime-agnostic)"]
STORE["StorageAdapter port"]
end
FILE[("storage/file.ts<br/>bookmarks.json, atomic writes")]
DO[("Durable Object storage<br/>strongly consistent")]
RAM[("storage/memory.ts")]
CD --> STDIO
IN --> STDIO
CD -.->|"remote: workers.dev/mcp"| CF
T --> MEM
STDIO --> Server
HTTP --> Server
CF --> Server
MEM --> Server
TOOLS --> Domain
RES --> Domain
PROMPTS --> Domain
STORE --> FILE
STORE --> DO
STORE --> RAMThe three MCP primitives — who controls what
Primitive | Controlled by | This server | Typical UI |
Tools | the model — the LLM decides when to call them |
| tool-use with permission prompt |
Resources | the application — the client attaches them as context |
| "attach context" picker |
Prompts | the user — explicitly invoked |
| slash command / menu |
Flows
1. Connection lifecycle (initialize handshake)
Every MCP session, on any transport, starts with the same three-step handshake in which client and server negotiate protocol version and capabilities:
sequenceDiagram
participant C as Client (Claude)
participant S as bookmark-mcp
C->>S: initialize (protocolVersion, capabilities, clientInfo)
S-->>C: result (serverInfo, capabilities: tools/resources/prompts, instructions)
C->>S: notifications/initialized
Note over C,S: Session is live
C->>S: tools/list
S-->>C: 4 tools with JSON Schemas + annotations
C->>S: resources/list · prompts/list
S-->>C: resource & prompt catalogs
Note over C,S: ... normal operation (see flow 2) ...
C->>S: close / SIGTERM
S->>S: flush write queue, close transport2. Tool call flow (what happens on "bookmark this URL")
sequenceDiagram
actor U as User
participant L as LLM
participant C as MCP Client
participant S as server.ts
participant D as store.ts
U->>L: "Save https://ex.com/post with tag rust"
L->>C: tool_use: add_bookmark {url, tags:["rust"]}
C->>S: tools/call add_bookmark
S->>S: Zod validates input against schema
alt input invalid
S-->>C: result { isError: true, "Invalid URL ..." }
Note over L: LLM reads the error and self-corrects
else input valid
S->>D: store.add(...)
alt duplicate URL
D-->>S: DuplicateUrlError
S-->>C: result { isError: true, "already bookmarked (id ...)" }
else success
D->>D: atomic write: tmp file + rename
D-->>S: Bookmark
S-->>C: result { content: [text], structuredContent: {bookmark} }
end
end
C->>L: tool result
L->>U: "Saved! It's in your reading list under 'rust'."Two error channels, used deliberately:
In-band tool errors (
isError: true) for expected business failures — duplicates, not-found, invalid input. The LLM sees the message and can recover (e.g. search for the existing bookmark instead).Protocol errors (JSON-RPC errors / thrown exceptions) only for unexpected bugs.
3. Streamable HTTP session lifecycle (Node self-hosted variant)
The stdio transport is one process per client — no session management needed. The Node remote server uses Streamable HTTP with explicit sessions:
sequenceDiagram
participant C as Remote client
participant H as http.ts (node:http)
participant T as StreamableHTTPServerTransport
participant S as McpServer (per session)
C->>H: POST /mcp (initialize, no session header)
H->>H: validate Origin header (DNS-rebinding defense)
H->>T: new transport + sessionIdGenerator()
H->>S: createServer(store).connect(transport)
T-->>C: 200 + Mcp-Session-Id: <uuid>
C->>H: POST /mcp (Mcp-Session-Id: <uuid>) — tools/call etc.
H->>T: route to session's transport
T-->>C: response (JSON or SSE stream)
C->>H: GET /mcp (Mcp-Session-Id) — optional
T-->>C: SSE stream for server→client notifications
C->>H: DELETE /mcp (Mcp-Session-Id)
T->>H: onsessionclosed → remove from session mapAll sessions share one BookmarkStore, so the data is consistent across clients; each session gets its own McpServer instance, so protocol state never leaks between clients.
4. Persistence: why writes can't corrupt the data
Locally (FileStorage adapter):
flowchart TD
A["tool handler mutates Map"] --> B["persist() appends to write queue"]
B --> C{previous write done?}
C -- "no" --> W["wait (serialized writes)"] --> D
C -- "yes" --> D["write bookmarks.json.PID.tmp"]
D --> E["rename() over bookmarks.json — atomic on POSIX"]
E --> F["crash at any point ⇒ old file intact"]In production the Durable Object gives the same guarantees for free: its storage API is transactional, and the DO is single-threaded so writes are serialized by the platform itself.
Production: Cloudflare Workers
worker.ts is the production entrypoint. The stateless Worker routes every request to one named Durable Object instance, which owns the data and runs the MCP server:
sequenceDiagram
participant C as MCP client (Claude)
participant W as Worker (edge, stateless)
participant D as Durable Object "default"
participant S as DO storage (SQLite-backed)
C->>W: POST https://bookmark-mcp.you.workers.dev/mcp
W->>D: idFromName("default") → stub.fetch(request)
Note over D: first request after cold start?
D->>S: read + Zod-validate persisted store
D->>D: fresh McpServer + WebStandard transport<br/>(stateless: no Mcp-Session-Id)
D->>S: transactional write on mutation
D-->>C: JSON-RPC response (plain JSON)Why this shape:
Stateless MCP (
sessionIdGenerator: undefined,enableJsonResponse: true): serverless requests may hit any isolate, so there are no sticky sessions to manage — each POST is self-contained. This is the recommended pattern for serverless MCP hosting.One DO = the consistency boundary. DO storage is strongly consistent and the instance is single-threaded, so concurrent clients can't corrupt data — the platform replaces both the atomic file writes and the write queue we need locally.
McpAgentalternative: Cloudflare'sagentsframework is the batteries-included route (per-session DOs, hibernation, OAuth templates). It needs external shared storage (KV/D1) because each session gets its own DO; the single shared DO here keeps the showcase self-contained and dependency-light. Reach forMcpAgentwhen you need server→client notifications or the OAuth flow.Multi-tenancy is one line away: derive the DO name from the authenticated user (
idFromName(userId)) and every user gets an isolated store.
Deploy
npx wrangler login # once
npm run deploy # builds + ships; prints https://bookmark-mcp.<you>.workers.devConnect Claude to the deployed server:
claude mcp add --transport http bookmarks https://bookmark-mcp.<you>.workers.dev/mcpLocal test of the exact production code path (runs in workerd, with a local DO):
npm run dev:worker # http://localhost:8787/mcp + /healthzBefore sharing the URL publicly, add auth — simplest is Cloudflare Access in front of the route; the full-fidelity option is the MCP OAuth 2.1 flow (workers-oauth-provider). The free plan (100k requests/day, SQLite-backed DOs included) comfortably covers personal use.
Production patterns demonstrated
Concern | Where | Pattern |
stdout discipline | On stdio, stdout is the protocol. One stray | |
Validation at the boundary | Zod raw shapes with | |
Structured output | Tools declare | |
Tool annotations |
| |
Recoverable errors | Business failures are | |
Pluggable storage | Runtime-agnostic domain layer + 2-method | |
Durable writes | Locally: temp-file + | |
Remote security | Origin validation, | |
Graceful shutdown | both entrypoints | SIGINT/SIGTERM close sessions and the transport before exiting. |
Testing | A real | |
Config via env | Matches how MCP clients pass configuration ( |
Production checklist (what's still missing before a public launch)
The Workers deployment already covers TLS, scaling, durable storage, and observability (wrangler tail / dashboard logs). What this showcase deliberately leaves out:
Authentication — the MCP spec mandates OAuth 2.1 for remote servers. On Cloudflare:
workers-oauth-provider(full spec flow) or Cloudflare Access with a service token (pragmatic personal setup). On Node:@modelcontextprotocol/sdk/server/authhelpers.Multi-tenancy — currently all clients share one bookmark collection; derive the DO name from the authenticated user to isolate stores.
Rate limiting & request size caps — Cloudflare WAF rules or a rate-limit binding.
Server→client notifications — the stateless Worker pattern has no SSE channel; if you need
listChangednotifications or progress streams, move to session-managed transports (Nodehttp.tsalready does this; on Workers useMcpAgent).
Extending the server
Adding a capability is a three-step pattern — schema, domain, registration:
Define the input shape in schemas.ts with
.describe()on every field.Add the operation to store.ts (plus a typed error class if it can fail in an expected way).
Register it in server.ts with
registerTool/registerResource/registerPrompt, and add a case to server.test.ts.
Debugging
npm run inspect # MCP Inspector: interactive UI for tools/resources/prompts
LOG_LEVEL=debug npm run dev # verbose stderr logs (Node)
npm test # full protocol round-trip without any client
npm run dev:worker # production code path locally (workerd + local DO)
npx wrangler tail # live logs from the deployed WorkerAvailable Tools
4 toolsadd_bookmarkAdd bookmarkA
Save a URL to the user's reading list. Rejects duplicate URLs. Returns the created bookmark including its generated id.
| Name | Required | Description | Default |
|---|---|---|---|
| url | Yes | URL to bookmark, e.g. https://example.com/article | |
| tags | No | Up to 10 tags, e.g. ['typescript', 'testing'] | |
| notes | No | Optional free-form notes | |
| title | No | Title for the bookmark. Defaults to the URL's hostname. |
Output Schema
| Name | Required | Description |
|---|---|---|
| bookmark | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Adds context beyond annotations by stating duplicate rejection and return of created bookmark with id. No contradiction with annotations (readOnlyHint=false, etc.).
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences with zero waste; front-loaded with the primary action and key behaviors.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Covers core behavior, duplicate rejection, and return value. With full schema and annotations, it's mostly complete, though could mention scope (user's own list) or error handling.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so all parameters are described in the schema. Description adds no additional parameter-level meaning beyond what's in the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description clearly states the action ('Save a URL to the user's reading list'), the specific resource, and distinguishes from siblings like delete_bookmark and mark_read by focusing on creation.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Mentions rejecting duplicates, which implies not to add existing URLs, but lacks explicit guidance on when to use this tool versus alternatives like search_bookmarks or mark_read.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
delete_bookmarkDelete bookmarkADestructive
Permanently delete a bookmark from the reading list.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | Id of the bookmark to delete |
Output Schema
| Name | Required | Description |
|---|---|---|
| deleted | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description aligns with annotations (destructiveHint=true) by stating 'permanently delete', and adds the context 'from the reading list', which is not covered by annotations. No contradictions.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single sentence, concise, and front-loaded with the key action and resource. Every word is necessary, no extraneous information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple tool with 1 parameter and an output schema, the description is adequate. It covers the purpose and effect, though it does not mention the output or any side effects beyond deletion.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% with a single parameter 'id' described in the schema. The description adds no additional meaning beyond the schema's own description, so a baseline score of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the verb 'Permanently delete' and the resource 'bookmark from the reading list', making the tool's purpose explicit and distinguishing it from sibling tools like add_bookmark, mark_read, and search_bookmarks.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No guidance is provided on when to use or not use this tool. It only states what it does, without mentioning alternatives or prerequisites, leaving the agent without context for selection.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
mark_readMark bookmark as readAIdempotent
Mark a bookmark as read. Safe to call repeatedly.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | Id of the bookmark to mark as read |
Output Schema
| Name | Required | Description |
|---|---|---|
| bookmark | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description adds 'safe to call repeatedly', reinforcing the idempotentHint annotation. However, it does not elaborate on what happens if the bookmark doesn't exist or other edge cases. Given annotations cover destructive and idempotent hints, the description adds minimal extra transparency.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Extremely concise: two short sentences with no redundancy. The action is front-loaded, and every word adds value.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple idempotent mutation with one parameter and an output schema, the description is sufficient. It covers the core behavior and safety, though it could mention return type or error behavior (but output schema likely handles that).
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema already fully describes the single 'id' parameter (100% coverage). The tool description adds no additional semantic information beyond what the schema provides.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the action (mark a bookmark as read) and distinguishes it from sibling tools (add, delete, search) which serve different purposes.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly mentions it is safe to call repeatedly, indicating idempotency. Although it doesn't compare to alternatives, the tool's simple nature and distinct siblings make usage clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_bookmarksSearch bookmarksARead-only
Search the reading list by free text, tag, and/or read status. Call without arguments to list the most recent bookmarks.
| Name | Required | Description | Default |
|---|---|---|---|
| tag | No | Only return bookmarks carrying this tag | |
| limit | No | Maximum results to return | |
| query | No | Case-insensitive text matched against title, URL, and notes. Omit to list all. | |
| unreadOnly | No | Only return unread bookmarks |
Output Schema
| Name | Required | Description |
|---|---|---|
| total | Yes | Number of bookmarks returned |
| bookmarks | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, consistent with description. Description adds the behavior of listing most recent bookmarks when called without arguments, but otherwise does not elaborate on return format, pagination, or other behavioral details beyond what annotations provide.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences: first states purpose and search dimensions, second notes the default behavior. Very efficient, no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Output schema exists, so return values are covered. Description covers all intended uses (search, list) and parameter categories. Given low complexity and good schema support, it is completely adequate.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema has 100% coverage with descriptions for all 4 parameters. The description summarizes them concisely but adds no new meaning beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description clearly states verb 'search' and resource 'reading list', specifies searchable dimensions (free text, tag, read status) and a default behavior (list recent). It distinguishes from siblings that add, delete, or mark read.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Description explicitly states when to use (search by criteria or list recent) but does not directly mention when not to use or point to siblings as alternatives. The context of sibling tools implies alternatives, but the description itself lacks explicit guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.
4 tool updates
v1.0.0- First observed
add_bookmark - First observed
delete_bookmark - First observed
mark_read - First observed
search_bookmarks
TDQS
Each tool targets a distinct operation: add, delete, mark as read, and search. There is no overlap or ambiguity.
All tools follow a consistent verb_noun pattern: add_bookmark, delete_bookmark, mark_read, search_bookmarks. The pattern is uniform and intuitive.
Four tools is an appropriate scope for a bookmark manager, covering essential operations without unnecessary bloat.
The tool set covers the basic CRUD and search functionality. A minor gap is the lack of an update tool for bookmark metadata beyond read status, but the core is solid.
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
Search, label, and manage your X (Twitter) bookmarks from any MCP client via Tweetsmash
MCP server for Russian books search, details, and recommendation candidates.
Search and save to your Purl read-it-later knowledge base from any MCP client.
The Mercado Pago MCP Server implements the Model Context Protocol to provide AI agents and LLMs with access to Mercado Pago's APIs and tools within compatible development environments. It acts as an intermediary that translates Mercado Pago resources into executable functions (tools) that AI applications can invoke to perform actions and automate flows. The server simplifies integration, enables using documentation to implement or improve code, and optimizes operations through natural language interactions without manual implementations.
Related MCP Servers
- AlicenseCqualityCmaintenanceA local-first MCP server that turns browser bookmark exports into a searchable knowledge base with classification, merging, full-text indexing, and Chrome integration.20MIT
- AlicenseNot gradedqualityCmaintenanceAn MCP server for Linkding bookmarks and web archival, enabling Claude to search, add, tag, archive, and delete bookmarks including archival snapshots.MIT
- AlicenseNot gradedqualityBmaintenanceThis MCP server connects to a Linkwarden instance, enabling semantic search, filtering, and management of bookmarks through natural language.574MIT
- FlicenseNot gradedqualityBmaintenanceA stateless MCP server that lets AI coding agents consult a curated library of development bookmarks when making decisions. It provides read-only tools to search, inspect, and list curated items, plus a reusable decision prompt.1-
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/privatenesk/playground_mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server