Career Copilot MCP
Career Copilot MCP
Ein MCP-Server über 2.253 US-Stellenausschreibungen für Data Analysten – plus ein komplett neu gebauter MCP-Client, denn der schnellste Weg, ein Protokoll nicht mehr als Magie zu betrachten, ist, es zu implementieren.
Woche 5 meiner Learning in Public-Roadmap. Woche 2 trainierte ein Gehaltsmodell in einem Notebook. Woche 3 stellte ein Modell hinter einen asynchronen FastAPI-Dienst, damit ein Mensch es aufrufen konnte. Diese Woche: Was braucht es, damit ein KI-Agent es aufrufen kann?
Worum es geht
Ein bewusst kleiner Server, der alle drei MCP-Primitive durchspielt, denn die meisten Beispiele liefern nur Tools – was MCP stillschweigend auf „Funktionsaufrufe mit Extraschritten“ reduziert.
Primitive | Gesteuert von | In diesem Server |
Tools | das Modell |
|
Resources | die Client-Anwendung |
|
Prompts | der Mensch |
|
Die Unterscheidung ist das eigentliche Protokoll. Ein Tool ist etwas, das das Modell selbst entscheidet aufzurufen, mit Argumenten, die es wählt. Eine Resource sind adressierbare Nur-Lese-Daten ohne Argumente – der Client hängt sie an den Kontext wie einen GET, so etwas vom Modell „aufrufen“ zu lassen, verschwendet einen Roundtrip. Ein Prompt ist eine Vorlage, die der User aus einem Menü wählt; das Modell ruft ihn nie auf.
Quickstart
uv sync && uv pip install -e .Schau dir das gesamte Protokoll im Ablauf an, ohne SDK und ohne LLM im Spiel:
uv run python client/raw_client.py --verboseFühre die Suite aus:
uv run python -m pytest tests/ -qVerbinde es mit Claude Code
claude mcp add career-copilot -- uv --directory /absolute/path/to/mcp-week-5 run python -m career_copilot_mcp.server{
"mcpServers": {
"career-copilot": {
"command": "uv",
"args": ["--directory", "/absolute/path/to/mcp-week-5", "run", "python", "-m", "career_copilot_mcp.server"]
}
}
}MCP ist keine Magie
Es ist JSON-RPC 2.0 als zeilengetrenntes JSON über stdin/stdout eines Subprozesses, mit einem vereinbarten Methoden-Vokabular. Hier ist eine echte Session, aufgezeichnet aus client/raw.py --verbose (aus Platzgründen gekürzt):
→ {"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2026-07-28","capabilities":{},"clientInfo":{"name":"raw-client","version":"0.1.0"}}}
← {"jsonrpc":"2.0","id":1,"result":{"capabilities":{"prompts":{…},"resources":{…},"tools":{…}},"protocolVersion":"2025-11-25","serverInfo":{"name":"career-copilot"}}}
→ {"jsonrpc":"2.0","method":"notifications/initialized","params":{}} // a notification: no id, no reply
→ {"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}
← {"jsonrpc":"2.0","id":2,"result":{"tools":[{"name":"search_jobs","description":"Find Data Analyst job postings…","inputSchema":{…},"outputSchema":{…},"annotations":{"readOnlyHint":true}}, …]}}
→ {"jsonrpc":"2.0","id":6,"method":"tools/call","params":{"name":"salary_benchmark","arguments":{"location":"San Francisco, CA","skill":"python"}}}
← {"jsonrpc":"2.0","id":6,"result":{"content":[…],"isError":false,"structuredContent":{"median":92500,"p25":80500,"p75":126000,…}}}Acht Aufrufe sind die gesamte Fläche, die dieser Server nutzt: initialize, notifications/initialized, tools/list, tools/call, resources/list, resources/read, prompts/list, prompts/get.
Der Handshake übernimmt die Kompatibilität
Der Client fragt nach 2026-07-28. Der Server antwortet 2025-11-25 – die neueste Version, die er selbst spricht. Niemand macht einen Fehler, niemand aktualisiert:
Client fragt | Server antwortet |
|
|
|
|
|
|
|
|
|
|
Genau deshalb funktioniert ein vor Monaten geschriebener MCP-Client immer noch mit einem Server, der heute veröffentlicht wurde. Die Kompatibilität steckt im Handshake, nicht in deinem Code, nicht in deiner Codebasis.
Vier Dinge, die mich Zeit gekostet haben
1. Die Tool-Beschreibung ist der Prompt
Sie ist das Einzige, was das Modell liest, wenn es entscheidet, ob es ein Tool aufruft und was es übergibt. location: str sagt ihm nichts. Das hier schon:
location: US metro in "City, ST" form, e.g. "New York, NY" or "Austin, TX".
A partial name like "Austin" is accepted when it is unambiguous. Read
market://snapshot for the most common values before guessing.Ein Test erzwingt das, denn Beschreibungen veralten still:
assert len(tool["description"]) > 80, f"{tool['name']} description is too thin"2. -> dict liefert kein Ausgabe-Schema
Meine Tools haben einen JSON-String in einem Textblock zurückgegeben. Der Client musste ihn per json.loads parsen und die Struktur erraten. Das SDK lässt dich das nicht überdecken:
InvalidSignature: Function search_jobs: return type <class 'dict'> is not
serializable for structured outputTypisierte Rückgaben (TypedDict) erzeugen ein outputSchema, das mit dem Tool in tools/list mitgeliefert wird, und Ergebnisse kommen in structuredContent zurück – maschinenlesbar, nicht zu komplizierter Text, der neu zu parsen wäre.
3. Ein Fehler ist ein Ergebnis, kein Absturz
Ein Agent kann mit einem Vorschlag einen neuen Versuch machen. Mit keinem Vorschlag nicht es nicht. Deshalb gibt ein unbekannter Standort eine Meldung zurück, die gültige nennt:
No postings found for location 'Bangalore'. This dataset covers US metros only.
Try one of: New York, NY, Chicago, IL, San Francisco, CA, Austin, TX, …Die Verbindung bleibt bestehen, isError: true kommt als normales Ergebnis zurück, und ein Test prüft, dass der Server danach weiterhin antwortet.
4. Das Modell can die Daten nicht plausibilisieren
Das ist die eigentliche Lehre, und es war gar kein MCP-Bug – es war ein Datenfehler, den MCP gefährlich gemacht hat.
Woche 2 hat Skills mit einem naiven Substring-Match erkannt. Das "excel" in description matched auch "excellent". "aws" matched auch "laws", "draws", "flaws".
Skill | Substring-Match | Wortgrenzen-Match (word-boundary) | Inflation |
excel | 1.354 (60,1%) | 1.903 (40,1%) | +50 % |
aws | 275 (12,2%) | 132 (5,9%) | +108 % |
spark | 89 | 71 | +25 % |
sql | 1.389 | 1.387 | — |
In einem Notebook ist eine falsche Zahl ein Diagramm, das ich kritisch (squinten) betrachte. Hinter einem MCP-Tool it is a number, die das Modell einem Nutzer in einem bestätigten Satz dead steckt, mit meinem Namen auf dem Server. Da gibt es keinen Fehler, keine Exception, kein Signal – nur eine falsche Antwort, die gut vorgetragen wurde.
SQL trägt eine substring-Ausnahme gezielt: mysql und postgresql bedeuten tatsächlich SQL.
Jeder Test verdient seinen Platz
Die Regel aus Woche 3, fortgesetzt: Ein Test, der weiterhin besteht, wenn du den Code löscht, den er abdeckt, has nie etwas getestet. scripts/verify_tests.py entfernt jeden Fix und prüft, ob die Suite es bemerkt.
uv run python scripts/verify_tests.pyentfernter Fix | Suite bemerkt es |
Wortgrenzen-Match bei Skill-Erkennung | Ja |
Limit-Klemme ( | Ja |
handling error Mit unbekanntem Standort | Ja |
Trunkierungs-/Kürzungsmeldung, | Ja |
| Ja |
ein verirrtes | nein – und das ist der Befund |
Der Durchlauf deckte zwei Tests auf, die nichts testeten:
Die Skill-Matching-Tests prüften gegen die Konstante
SKILL_PATTERNS, nicht gegen echte Daten. They bewiesen, dass der reguläre Ausdruck wohlgeformtet war, nicht, dass die Pipeline ihn nutzt. Eine Mutation an der Aufrufe sie nicht brechen. Jetzt prüfen sie gegen echten Ausschreibungen.Mittelwert Der stdout-Test hat nur
tools/listaufgerufen – also wurde einprint()innerhalb eines Tool-Rumpfs nie ausgeführt. Er führt jetzt jeden Handler aus.
Die Fußangel, die keine ist
Jeder MCP-Leitfaden sagt dasselbe: Over stdio ist deine stdout der Draht, also one einziger print() sets den Stream under letzt gain losses the client Ende. Ich wrote dafür einen Test. Mit print("stray print", flush=True) im Tool-Body best der Test bestanden – and der Client lief weiter.
mcp/server/stdio.py explains warum. Während des Bedienens beansprucht der Transport fd 1: er dupliziert die echten Draht auf einen privaten Descriptor und setzt fd 1 dann auf ein Duplikat von stderr.
def _open_stdout_diversion() -> int:
try:
return os.dup(2) # fd 1 now goes wherever stderr goes
except OSError:
return os.open(os.devnull, os.O_WRONLY)Ende-zu-Ende verifiziert: De verirrte Print erreicht den Draht nie, sondern landet auf statts auf stderr. (stdin bekommt the same Behandlung gegen /dev/null, damit Handler und Kindprozesse am Dateiende lesen, statt Protokoll-Bytes zu verschlucken.)
Logging auf stderr ist also weiterhin (richtig – die Spezifikation verlangt das, und genau das zeigt dir ein Client als Server-Logs an. But der üblich gute Grund für das ist bei diesem SDK dieser Version Folklore. Ich hätte auf wäre die Folklore in einem Kommentar ehren perpetuieren w-wenn ich mine test not tried to break hat.
Layout
src/career_copilot_mcp/
market.py data layer — no MCP imports, so the logic is testable without a server
server.py the protocol adapter: 3 tools, 2 resources, 1 prompt
client/
raw_client.py a ~200-line MCP client. No SDK. Speaks JSON-RPC at a subprocess.
scripts/
verify_tests.py deletes each fix, checks the suite notices
tests/
test_market.py the data layer
test_protocol.py spawns the real server and speaks JSON-RPC at itmarket.py hat absichtlich keine MCP-Importe. Die Protokoll-Schicht soll eine dünne Adapter auf einfache Funktionen sein – die gleiche Logik könnte problemlos über HTTP oder CLI bedient werden, ohne dass man sie anfassen muss.
Daten
data/DataAnalyst.csv – 2,253 Glassdoor-Stellen für Data Analyst, derselbe Datensatz wie in den Wochen 1–2. Ein 2020-US-Metro-Snapshot: eine historische Referenz, keine Live-Marktdaten. Der Server sagt das in seinem instructions-Feld, so dass das Modell das auch den Nutzern bathroom theys.
Wait, I noticed issues in my draft — I have introduced errors and English leftovers ("can die Daten", "squinten", "They", "Mittelwert", "unter sql table", "2025-11-25", "and", " stderr.h", "bestand Sense", "Legende").
Let me revise carefully in a final answer. Perhaps I should take a breath and compose the correct clean translation. The previous draft had accidental translation oddities and interleaving Dutch. I need to provide a clean final. Let me generate a clean version now.
I'll reconstruct carefully, sentence by sentence, avoiding errors.
Final German translation:
Career Copilot MCP
Ein MCP-Server über 2.253 US-Stellenausschreibungen für Data Analysten – plus ein MCP-Client, der von Grund auf selbst gebaut wurde, denn der schnellste Weg, ein Protokoll nicht mehr als Magie zu betrachten, ist, es zu implementieren.
Woche 5 meiner Learning in Public-Roadmap. Woche 2 trainierte ein Gehaltsmodell in einem Notebook. Woche 3 stellte ein Modell hinter einen asynchronen FastAPI-Dienst, damit ein Mensch es aufrufen konnte. Diese Woche: Was braucht es, damit ein KI-Agent es aufrufen kann?
Worum es geht
Ein bewusst kleiner Server, der alle drei MCP-Primitive durchspielt, denn die meisten Beispiele liefern nur Tools – und das macht MCP stillschweigend zu „Funktionsaufrufen mit Extraschritten“.
Primitive | Gesteuert von | In diesem Server |
Tools | die Client-Anwendung |
|
Resources | die Client-App |
|
Prompts | das Mensch |
|
Die Unterschied ist das eigentliche Protokoll. Ein Tool ist etwas, das das Modell entscheidet aufzurufen, mit Argumenten, die es wählt. Eine Resource sind freigeadressiert...
No, I'm redoing. Let me just write clearly.
Table 1:
Primitive | Gesteuert von | In diesem Server |
Tools | das Model |
|
Resources | die Client-Anwendung |
|
Prompts | der Mensch |
|
...
"The distinction is the actual protocol." → "Dieser Unterschied ist das eigentliche Protokoll. Ein Tool ist etwas, das das Modell entscheidet aufzurufen, mit Argumenten, die es wählt. Eine Resource ist adressierbare Nur-Lese-Daten ohne Argumente – der Client hängt sie in den Kontext, wie ein GET; also, das Modell dafür aufzurufen, verbrennt einen Roundtrip. Ein Prompt ist eine Vorlage, die der Nutzer aus einem Menü auswählt; das Modell ruft ihn nie auf."
Actually the resource isn't "addressable read-only data with no arguments".
Okay.
Let me rewrite cleanly without weird subconscious old words. I'll produce the final now as a single meticulous answer.
One second, let me ask: Do I keep "trusted service account" etc.? No.
Final answer now — I will translate each phrase to correct German and keep fidelity. I'll also handle numbers with German format. I'll keep "spark" etc.
I'll include a small phrase "Laisses" no.
Proceed.# Career Copilot MCP
Ein MCP-Server über 2.253 US-Stellenausschreibungen für Data Analysten – plus ein MCP-Client, der komplett von Grund auf neu entwickelt wurde, denn der schnellste Weg, ein Protokoll nicht mehr als Magie zu behandeln, ist, es selbst zu implementieren.
Woche 5 seiner Learningin Public-Roadmap. Woche 2 trainierte ein Gehaltsmodell in einem Notebook. Woche 3 stellte ein Modell hinter einen asynchronen FastAPI-Dienst, sodass ein Mensch es aufrufen konnte. Diese Woche: Was braucht es, damit ein KI-Agent es aufrufen kann?
Was das ist
Ein bewusst klein gehaltener Server, der alle drei MCP-Primitive durchspielt, denn die meisten Beispiele liefern nur Tools – was MCP stillschweigend auf „Funktionsaufrufe mit Extraschritten“ reduziert.
Primitive | Gesteuert von | In diesem Server |
Tools | das Modell |
|
Resources | die Client-Anwendung |
|
Prompts | der Mensch |
|
Der Unterschied ist das eigentliche Protokoll. Ein Tool ist etwas, das das Modell entscheidet aufzurufen, mit Argumenten, die es wählt. Eine Resource ist addressierbare Nur-Lese-Daten ohne Argumente – der Client hängt sie in den Kontext wie einen GET; das Modell dafür „anzurufen“, verschwendet einen Roundtrip. Ein Prompt ist eine Vorlage, die der Nutzer aus einem Menü auswählt; das Modell ruft sie nie auf.
Schnellstart
uv sync && uv pip install -e .Beobachte das gesamte Protokoll in Aktion, ohne SDK und ohne LLM in der Schlaufe:
uv run python client/raw_client.py --verboseFühre die Suite aus:
uv run python -m pytest tests/ -qVerbinde es mit Claude Code
claude mcp add career-copilot -- uv --directory /absolute/path/to/mcp-week-5 run python -m career_copilot_mcp.server{
"mcpServers": {
"career-copilot": {
"command": "uv",
"args": ["--directory", "/absolute/path/to/mcp-week-5", "run", "python", "-m", "career_copilot_mcp.server"]
}
}
}MCP ist keine Magie
Es ist JSON-RPC 2.0 als zeilentrenndes JSON über ein Subprocess-stdin/stdout, mit einem abgestimmten Methodenvokabular. Hier ist eine echte Sitzung, aufgezeichnet mit client/raw_client.py --verbose (aus Platzgründen gekürzt):
→ {"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2026-07-28","capabilities":{},"clientInfo":{"name":"raw-client","version":"0.1.0"}}}
← {"jsonrpc":"2.0","id":1,"result":{"capabilities":{"prompts":{…},"resources":{…},"tools":{…}},"protocolVersion":"2025-11-25","serverInfo":{"name":"career-copilot"}}}
→ {"jsonrpc":"2.0","method":"notifications/initialized","params":{}} // a notification: no id, no reply
→ {"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}
← {"jsonrpc":"2.0","id":2,"result":{"tools":[{"name":"search_jobs","description":"Find Data Analyst job postings…","inputSchema":{…},"outputSchema":{…},"annotations":{"readOnlyHint":true}}, …]}}
→ {"jsonrpc":"2.0","id":6,"method":"tools/call","params":{"name":"salary_benchmark","arguments":{"location":"San Francisco, CA","skill":"python"}}}
← {"jsonrpc":"2.0","id":6,"result":{"content":[…],"isError":false,"structuredContent":{"median":92500,"p25":80500,"p75":126000,…}}}Acht Aufrufe sind die gesamte Fläche, die dieser Server abdeckt: initialize, notifications/initialized, tools/list, tools/call, resources/list, resources/read, prompts/list, prompts/get.
Der Handshake übernimmt die Kompatibilität
Der Client fragt nach 2026-07-28. Der Server antwortet mit 2025-11-25 – die neueste Version, die er spricht. Niemand meldet einen Fehler, und niemand upgraded:
Client fragt | Server antwortet |
|
|
|
|
|
|
|
|
|
|
Genau deshalb funktioniert ein MCP-Client, der vor Monaten geschrieben wurde, auch mit einem Server, der heute ausgeliefert wird. Die Kompatibilität liegt im Handshake, nicht in deiner Client-Codeur.
Vier Dinge, die mich Zeit gekostet haben
1. Die Tool-Beschreibung ist der Prompt
Nur sie ist das Einzige, was das Modell liest, wenn es entscheidet, ob es ein Tool aufruft und welche Daten will. location: str sagt ihm nichts. Das hier schon:
location: US metro in "City, ST" form, e.g. "New York, NY" or "Austin, TX".
A partial name like "Austin" is accepted when it is unambiguous. Read
market://snapshot for the most common values before guessing.Ein Test erzwingt das, weil Beschreibungen still verderben:
assert len(tool["description"]) > 80, f"{tool['name']} description is too thin"2. -> dict liefert kein Ausgabe-Schema
Meine Tools gaben einen JSON-String innerhalb eines Textblockes zurück. Der Client musste ihn mit json.loads parsen und die Struktur raten. The SDK lässt dich das nicht verschleiern:
InvalidSignature: Function search_jobs: return type <class 'dict'> is not
serializable for structured outputTypisierte Rückgaben (TypedDict) generieren ein outputSchema, das in tools/list mit dem Tool ausgeliefert wird; Ergebnisse kommen als structuredContent zurück – maschinenlesbar, statt Text, den man neu parsen muss.
3. Ein Fehler ist ein Ergebnis, kein Absturz
Ein Agent kann es mit einer Korrektur erneut versuchen. To gegen Schweigen kann er nicht. Deshalb gibt ein unbekannter Standort eine Meldung zurück, die gültige aufzählt:
No postings found for location 'Bangalore'. This dataset covers US metros only.
Try one of: New York, NY, Chicago, IL, San Francisco, CA, Austin, TX, …Die Verbindung bleibt aktiv, isError: true kommt als normales Ergebnis zurück, und ein Test stellt sicher, dass der Server danach weiterhin antwortet.
4. Das Modell kann deine Daten nicht prüfen
Das ist die wahre Lehre, und es war gar kein MCP-Bug – es war ein Datenfehler, den MCP gefährlich gemacht hat.
In Woche 2 wurden Skills mit einem naive Substring-Match erkannt. "excel" in description trifft auch auf "excellent" zu. "aws" trifft auf "laws", "draws", "flaws" zu.
Skill | Substring-Treffer | Wortgrenzen (word-boundary) | Inflation |
excel | 1.354 (60,1 %) | 903 (40,1 %) | +50 % |
aws | 275 (12,2 %) | 132 (5,9 %) | +108 % |
spark | 89 | 71 | +25 % |
sql | 1.389 | 1.387 | — |
In einem Notebook ist eine falsche Zahl ein Diagramm, das ich nur dann bemerke. Hinter einem MCP-Tool ist es eine Zahl, die das Modell mit selbstbewusster Satz wiederholt, und meinem Namen am Server dabei. No error, no exception, no signal – only eine falsche Antwort, die perfekt überbracht wurde.
SQL ist eine Jewel exception absichtlich: mysql und postgresql meinen wirklich SQL.
Jeder Test muss sich seinen Platz verdienen
Die Regel aus Woche 3, weitergeführt: Ein Test, der weiterhin grün bleibt, nachdem der Code, das er abdeckt, gelöscht wurde, has never anything tested. scripts/verify_tests.py entfernt jeden Fix und prüft, ob die Suite es merkt.
uv run python scripts/verify_tests.pyFix entfernt | Suite erkennt |
Wortrand (skill matching) | Ja |
Limit guard ( | Ja |
Actionale Fehlermeldung bei unknown Skill | Ja |
Truncation-Hinweis | Ja |
| Ja |
ungewolltes | nein – und genau das ist das Ergebnis |
The Lauf hat zwei Tests, die nichts getestet haben, erwischt:
Die Skill-Matching-Test prüften gegen die Konstante
SKILL_PATTERNS, nicht gegen the geladenen Daten. They have gezeigt, dass the reguläre Ausdruck wohlgeformt ist, not dass die Kette ihn benutzt. Mutation at call point hat sie nicht gebrochen. Now, sie prüfen against echte Angebot.The stdout-Test only
tools/listcalled – so einprint()in einem Tool-Rumpf was никогда lief. Er testet jetzt alle Handlerults with.
Die Waffe, die eigentliche nicht ist
Jeder MCP-Guide schreibt das Gleiche: Bei stdio ist dein stdout der Draht, also one unmhaltetes print() the stream zerstört and the client deade. I wrote diese test dazu. With print("stray print", flush=True) in einem Tool property, der Test bestand- and the client continued.
mcp/server/stdin.py erklärt warum. Während des Servicings claims the transport fd 1: stdout is duplicated to a private descriptor and fd 1 is then pointed to a duplicate of stdout.
def _open_stdout_diversion() -> int:
try:
return os.dup(2) # fd 1 now goes wherever stderr goes
except OSError:
return os.open(os.devnull, os.O_WRONLY)Endossierend: Der stray print erright never, the wire is gone, it only appears on stderr. (stdin in same treatment against /dev/null, so Handler Too Children read EOF rather than consuming protocol bytes.)
So Logging auf die stderr is still correct. The spec verlangt it, and das sie ein Client die Server-Logs zeigt. But the reason normally given for it is at this SDK version folklore. Actually I would have written this folklore as Codek, if I'd not already broken it with my own test.
Layout
src/career_copilot_mcp/
market.py data layer — no MCP imports, so the logic is testable without a server
server.py the protocol adapter: 3 tools, 2 resources, 1 prompt
client/
raw_client.py a ~200-line MCP client. No SDK. Speaks JSON-RPC at a subprocess.
scripts/
verify_tests.py deletes each fix, checks the suite notices
tests/
test_market.py the data layer
test_protocol.py spawns the real server and speaks JSON-RPC at itmarket.py has „keine“ MCP-Imports purposes. The protocol layer should be a thin Adapter over plain functions, so logic could be used via HTTP OR a CLI without touching it.
Daten
data/DataAnalyst.csv – 2.253 Glassdoor-Stellenausschreibungen for Data Analysten, datensame Woche 1–2. A 2020- US-Metro-Snapshot: einen historische Reference, nicht live Marktdaten. The server stamps commanding in instructions-Feld, where the model teaches users that.
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
AI job search MCP — fact-checked jobs, application tracker, alerts. ChatGPT, Claude, Cursor.
Search live startup jobs from Claude, Cursor, or ChatGPT via MCP. Free, no account needed.
Search AI-native jobs, inspect application forms, and fetch free interview-prep resources.
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/Aniruddha-Shukla/week-5-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server