Inspiration

I built jobContext after getting laid off and finding that AI job-search help came with its own tax: every new conversation began cold.

I was repeatedly re-explaining my resume, what I had shipped, which companies were already in my pipeline, people I had met, my STAR stories, and the way I write. The context existed, but it was scattered across documents, tabs, and past chats. Copying it into every fresh session was exhausting when I needed that energy for the search itself.

I started by building a few small tools to stop re-explaining myself. They grew into jobContext.

What I built

jobContext is a living career workspace: applications, job search, materials, interviews, people, STAR stories, and the context behind them stay structured and persistent across sessions. It works as a desktop app, hosted dashboard, mobile companion, CLI, and MCP capability layer.

It is not another chat that gives advice and forgets the work. The person owns the workspace and stays in the loop; an agent can help move real work forward inside it.

For this challenge, I made the signed-in browser workspace agent-ready through WebMCP. A person and an in-browser agent can work from the same live pipeline: understand the search, find or assess a role, create materials, log the work, and leave the result where the person can inspect and use it. No new connector, separate OAuth flow, or blank-slate conversation is required.

How I built it

jobContext is built with Python, FastMCP, FastAPI, SQLite with a JSON audit trail, and a React dashboard.

After authentication, the dashboard asks the live FastMCP server for its tool list and registers the returned names, descriptions, and input schemas directly with document.modelContext. When an in-browser agent invokes a tool, the bridge sends a same-origin JSON-RPC request to the same stateless /mcp endpoint used by other clients.

The browser surface is not a second, hand-maintained API. It reflects the running MCP surface, so browser tools cannot quietly drift from the tools the app actually offers. The current surface has 12 consolidated tools and 104 actions behind them.

Challenges I ran into

More context is not better context. While improving document generation, I discovered that the system had accumulated more context about my writing style than about what I had actually done. That drove a retrieval-first redesign: token budgets, diagnostics, context ceilings, selective retrieval, and a clear separation between stored knowledge and prompt assembly. The lesson was simple: better context beats more context.

“No setup” still has to be safe. I wanted the browser agent to work with the signed-in dashboard, not make someone configure yet another connector. But a session cookie is not permission to trust every browser request. The server accepts that session only for same-origin requests to /mcp; a cross-site browser request cannot use it, while deliberate bearer-auth MCP clients still work.

A browser tool call is shorter than real document work. In-browser clients can time out before resume or cover-letter generation finishes. I added durable submit-and-poll generation so an agent can start work, return promptly, then retrieve the finished result instead of pretending a long-running job completed.

A generated file is not a finished workflow. If a draft lands untracked, it creates another loose end. Generated materials now automatically create or update the relevant pipeline entry. A read-only Generation Trust Report lets the person inspect the claims checked, verdict, correction passes, and durable audit record.

Trust has to be architectural. An interview question exposed a gap in my own system: I could observe non-deterministic AI output, but I could not yet prove that a generated claim was grounded. That became a deterministic provenance gate that checks factual claims against the source material on every generation and records the outcome. Prompt instructions alone were not enough.

What I learned

  • The useful unit of AI collaboration is not a prettier chat response. It is a shared, current workspace where the human can see what happened and decide what comes next.
  • WebMCP matters because it lets a page describe its live capabilities at runtime. That is fundamentally better than making a person configure a second integration or maintain a browser-only copy of an API.
  • Reducing friction can create more value than adding features. One of the most satisfying product moments was sharing a job from a phone and having the relevant workflow already waiting at the desk.
  • Good agent systems need grounded context, clear permission boundaries, durable work, and inspectable results. Those are product requirements, not cleanup work after the demo.

What changed during this challenge

The original jobContext project predates this challenge. The WebMCP agent surface and its supporting hardening below were built during the submission period.

  • The core bridge dynamically reflects the live FastMCP tool surface into document.modelContext and calls the signed-in, same-origin MCP endpoint.
  • Agent-driven testing exposed and fixed workspace-aware assessment, validation, and interview-prep round-trip issues.
  • I added provenance reporting, durable submit-and-poll generation for short browser timeouts, workflow instructions for in-browser agents, and automatic pipeline tracking for generated materials.

WebMCP implementation synopsis

The WebMCP work began by turning the existing hosted dashboard into an agent surface without creating a second browser-only tool API. The React app probes for document.modelContext, with the older navigator.modelContext alias retained as a compatibility fallback. After the user is authenticated, the bridge calls the live FastMCP server's tools/list endpoint, takes the returned tool names, descriptions, and input schemas, and registers those definitions with modelContext.registerTool(). When the browser agent invokes a registered tool, the bridge forwards the call as JSON-RPC over the same-origin, stateless /mcp endpoint already used by other MCP clients.

That architecture means the WebMCP surface is generated from the server's real capability layer. There is no separately maintained list of browser tools to drift out of date. At submission time, the live surface exposes 12 consolidated domain tools with 104 actions. New server-side actions can appear in WebMCP automatically through tools/list rather than requiring a second implementation.

The bridge also preserves the signed-in experience without turning the session cookie into ambient authority for arbitrary websites. Same-origin browser calls to /mcp may use the existing jobContext session. Cross-site requests are denied session-cookie authority using Sec-Fetch-Site, with Origin and Host checks as a fallback. Bearer-authenticated MCP clients and non-browser clients remain supported. This was built specifically so WebMCP could feel like part of the signed-in application while still enforcing an origin boundary around side-effecting tools.

Browser agents also exposed operational gaps that were easy to miss in ordinary chat or direct MCP use. Long-running resume and cover-letter generation can outlive a browser tool-call window, so jobContext gained a durable submit-and-poll control plane. The agent can submit generation work, receive a work-item identifier promptly, and later poll for completion rather than holding the browser call open. Remote LLM clients were then given finite request timeouts and stale-run reporting so a slow provider cannot silently occupy every dispatcher slot.

Agent-driven end-to-end testing also found workflow problems beyond the bridge itself. Assessments generated through WebMCP were initially missing workspace signals such as known contacts, application events, and scheduled interviews. That led to server-side signal injection and workspace-aware assessment behavior. Invalid personas were changed from soft warnings to explicit failures, repeated assessments gained reuse and deliberate force-regeneration semantics, and interview-prep and material-preview round trips were hardened based on real browser-agent use.

The trust layer was made visible to the browser agent as well. Resume and cover-letter generation already passed through grounding checks, but the result was not inspectable from chat. During the challenge, jobContext added a read-only Generation Trust Report backed by the durable provenance record. An agent can generate a document and then show the user the verdict, claims checked, unsourced violations, correction passes, enforcement mode, and record identifier. The correction loop was also hardened so revised content is re-checked rather than assuming the first correction succeeded.

The workflow was completed on the application side too. Generated material for an untracked company now creates the appropriate pipeline entry at an honest "materials drafted" state, so a successful generation does not leave an orphaned file. Public job-board support expanded with Ashby and Recruitee providers, and because the WebMCP bridge republishes tools/list, those actions became available to in-browser agents without a separate WebMCP code path.

Finally, the deployed surface was hardened for judges and future agent clients. The Chrome WebMCP origin-trial token was added to the image build, the public site and architecture documentation were refreshed around the shipped WebMCP model, and /llms.txt plus in-DOM breadcrumbs were added so agents that cannot see document.modelContext do not incorrectly conclude that the dashboard has no tool surface.

Submission-period evidence

The repository is public, and the dated Git history shows the WebMCP implementation landing during the challenge window. Representative commits and merges include:

  • Aug 27, 2026: 78e771c, "feat: WebMCP bridge: expose MCP tools to in-browser agents via the dashboard." This added the browser bridge, same-origin Streamable HTTP JSON-RPC client, dynamic tools/list registration, cross-site cookie guard, origin-trial support, docs, and WebMCP-specific tests.
  • Aug 27, 2026: PR #303 merged the WebMCP bridge, followed by PR #304 promoting it from QA to main.
  • Aug 28, 2026: fb4d1a8, WebMCP CSRF test hardening, plus judge-driven fixes to materials preview and assessment saving.
  • Aug 29, 2026: 67a8460, workspace-aware assessments based on failures exposed by ChatGPT through the WebMCP bridge.
  • Aug 30, 2026: PR #321 merged the WebMCP bridge bug-report fixes for workspace-aware generation, strict validation, and prep round trips.
  • Aug 30, 2026: 8a0bc03, surfaced the truth gate and control-plane attestation through chat so WebMCP users can inspect a Generation Trust Report.
  • Aug 30, 2026: 4763e14, added Ashby and Recruitee job-board actions that became available to WebMCP automatically through the reflected tools/list surface.
  • Aug 31, 2026: f6cdd9e, hardened the async control plane with finite remote-client timeouts and stale-run reporting.
  • Aug 31, 2026: 9bbc0fa, made generated documents automatically track their application workflow.
  • Aug 31, 2026: 7657908, refreshed the public site and architecture documentation around the shipped WebMCP system.
  • Aug 31, 2026: aba2f39, baked the WebMCP origin-trial token into the production image build.
  • Sep 1, 2026: dbb7272, added /llms.txt and in-DOM agent breadcrumbs, followed by PR #353 promoting the origin-trial and agent-discovery work to main.
  • Sep 1, 2026: PR #355 promoted the /llms.txt public-path fix to main.

The result is not a separate AI assistant bolted onto a career app. It is a human and an agent working from the same living career memory, through the same capability layer, in the browser where the work is already happening.

Built With

Share this project:

Updates

Submission history