Skip to main content
Glama
maraMoreir

career-agent

by maraMoreir

Career Agent

Career agent integrated with Claude Desktop via MCP. Finds job openings, calculates compatibility with your profile, customizes your resume legitimately, generates messages and responses, and keeps track of application history.

The final external action is always yours. The agent prepares; you click.


What's new in v1.1

Feature

How to use

Persistent job catalog

run_job_search collects and saves; list_matching_jobs queries

5 ATS providers

Greenhouse, Lever, Ashby, Workable, SmartRecruiters

Adzuna (BR national index)

fill in ADZUNA_APP_ID/ADZUNA_APP_KEY in .env

Configurable weights

edit data/config/scoring.json

11 score dimensions

includes .NET, SAP, tax, architecture, and backend focus

Scheduled search

.\scripts\schedule.ps1 -IntervalHours 2

Local dashboard

.\scripts\start-dashboard.ps1

Retry with backoff

automatic on all HTTP sources

Details of each source, with what was measured: docs/FONTES.md.


Related MCP server: job-search-mcp

Table of Contents

  1. Architecture

  2. Prerequisites

  3. Installation

  4. Configuration

  5. Claude Desktop Configuration

  6. How to start

  7. How to test

  8. How to add a new job source

  9. How to add a new resume

  10. How to register an application

  11. Example commands in Claude Desktop

  12. Current limitations

  13. Next steps


1. Architecture

Overview

                        Claude Desktop
                              |
              +---------------+---------------+
              |               |               |
        career-agent     job-search     career-files
         (MCP stdio)     (MCP stdio)     (MCP stdio)
              |               |               |
              +---------------+---------------+
                              |
                        career_core
              (dominio puro - nao conhece MCP)
                              |
         +--------+-----------+-----------+--------+
         |        |           |           |        |
      profile  scoring   applications  resume  job_sources
       (.md)   (7 dim.)  (SQLite+JSON) (tailor) (IJobSource)

Architectural decisions

Domain separated from adapters. All business rules live in src/career_core/, which doesn't import anything from MCP. The three server.py files are thin adapters: they translate arguments, call the domain, format the response. This allows testing 100% of the logic without starting any server.

SQLite as source of truth, JSON as mirror. SQLite provides transactional writes (history doesn't corrupt if the process dies mid-way) and cheap duplicate queries, with zero configuration — unlike PostgreSQL, which would require a server and credentials with no benefit at a single-person scale. The applications.json file continues to exist, rewritten atomically on every change, for visual inspection and Git versioning. It is write-only: never read back, so there's no risk of two sources diverging.

Score as pluggable dimensions. Each of the 7 dimensions is a class that implements IScoreDimension and knows how to score and explain a single aspect. JobScorer just sums and ranks. Adding a new dimension doesn't change the summer (Open/Closed).

Job sources behind an interface. IJobSource has four implementations: MockJobSource (offline), RemotiveJobSource and ArbeitnowJobSource (real public APIs, no authentication), and UnavailableJobSource (LinkedIn/Indeed/Gupy — declared, but in manual mode). Adding a source is writing a class and registering it; nothing else changes.

Single composition root. CareerServices builds the object graph. Servers don't instantiate dependencies by hand, and tests inject doubles.

Directory structure

career-agent/
├── pyproject.toml            # deps + config do pytest (fonte unica)
├── .env.example              # modelo de configuracao (versionado)
├── .env                      # sua configuracao real (NAO versionado)
│
├── src/career_core/          # DOMINIO - nao conhece MCP
│   ├── config.py             # Settings por ambiente
│   ├── models.py             # Job, CandidateProfile, Application, JobScore
│   ├── text.py               # normalizacao (aliases de stack, URL, empresa)
│   ├── security.py           # politica + maquina de estados (ApprovalGate)
│   ├── paths.py              # SandboxedFileSystem (jail em data/)
│   ├── errors.py             # hierarquia de erros de dominio
│   ├── logging_setup.py      # logging para stderr + arquivo
│   ├── services.py           # composition root
│   ├── job_input.py          # vaga colada -> Job normalizado
│   ├── profile/repository.py # perfil .md -> CandidateProfile
│   ├── scoring/              # dimensions.py (7 dimensoes) + scorer.py
│   ├── applications/         # repository.py, dedupe.py, builder.py
│   ├── resume/tailor.py      # personalizacao + FactGuard
│   └── job_sources/          # base.py, mock.py, http_sources.py,
│                             # unavailable.py, registry.py
│
├── mcp-career/               # MCP 1 - logica de carreira
├── mcp-job-search/           # MCP 2 - obtencao de vagas
├── mcp-career-files/         # MCP 3 - leitura de arquivos (sandbox)
│
├── data/                     # UNICO diretorio visivel ao career-files
│   ├── profile/              # profile.md, skills.md, preferences.md
│   ├── resumes/              # curriculo-principal.md (+ variantes)
│   └── applications/         # applications.db (verdade) + .json (espelho)
│
├── agent/career-agent.md     # instrucoes de comportamento do agente
├── scripts/                  # install.ps1, start.ps1, test.ps1, configure-*
├── tests/                    # pytest
└── docs/                     # SECURITY.md, SCORING.md, ARCHITECTURE.md

2. Prerequisites

Requirement

Version

Notes

Windows

10/11

tested on Windows 11

Python

>= 3.11

python --version

uv

any

install.ps1 installs it if missing

Claude Desktop

current

required to use the MCPs

Git

optional

to version the project


3. Installation

cd C:\career-agent
powershell -ExecutionPolicy Bypass -File .\scripts\install.ps1

The script checks Python, installs uv if missing, creates .venv, installs dependencies, creates the data/ tree, generates .env from .env.example, and validates that the three MCPs start up.

To also write the Claude Desktop configuration in the same step:

powershell -ExecutionPolicy Bypass -File .\scripts\install.ps1 -ConfigureClaude

4. Configuration

4.1 Fill in your profile

These files are the source of truth. The agent never claims anything that isn't in them.

File

What to put

data/profile/profile.md

name, contacts, summary, education, blocked companies

data/profile/skills.md

technologies, architecture, domains

data/profile/preferences.md

target roles, seniority, modality, cities, salary

data/resumes/curriculo-principal.md

your complete resume

Look for [FILL_IN] — these are the fields the agent can't invent.

Two of them change the score right away:

  • Years of experience in profile.md: while set to not informed, the "years" part of the Experience dimension stays neutral. The agent does not infer this number.

  • Minimum / Target in preferences.md: while set to [FILL_IN], the Salary dimension stays neutral for jobs with a published range.

4.2 Adjust .env

CAREER_DATA_ROOT=C:\career-agent\data
CAREER_MIN_SCORE=70

JOB_SEARCH_ENABLE_NETWORK=true
JOB_SEARCH_SOURCES=ats
JOB_SEARCH_ATS_COMPANIES=greenhouse:stone,ashby:nubank,greenhouse:vtex,...
JOB_SEARCH_USER_AGENT=career-agent/1.0 (personal job search; contact: SEU-EMAIL)

Put your email in the User-Agent — identifying yourself is the polite way to consume a public API.

The ats source only finds jobs from companies you list. To add one, open its careers page and look at the URL:

Careers page URL

Add

job-boards.greenhouse.io/SLUG

greenhouse:SLUG

jobs.lever.co/SLUG

lever:SLUG

jobs.ashbyhq.com/SLUG

ashby:SLUG

Companies whose careers page is on Gupy can't be added — Gupy doesn't expose public search. For those, use manual mode.

There is no LinkedIn credential variable in this project. That's deliberate.


5. Claude Desktop Configuration

powershell -ExecutionPolicy Bypass -File .\scripts\configure-claude-desktop.ps1

The script backs up the existing file (.backup-YYYYMMDD-HHMMSS), preserves all your current settings and MCPs, and only adds/updates the three Career Agent entries.

Manual

File: %APPDATA%\Claude\claude_desktop_config.json (in your case: C:\Users\Roger\AppData\Roaming\Claude\claude_desktop_config.json)

{
  "mcpServers": {
    "career-agent": {
      "command": "C:\\career-agent\\.venv\\Scripts\\python.exe",
      "args": ["C:\\career-agent\\mcp-career\\server.py"]
    },
    "job-search": {
      "command": "C:\\career-agent\\.venv\\Scripts\\python.exe",
      "args": ["C:\\career-agent\\mcp-job-search\\server.py"]
    },
    "career-files": {
      "command": "C:\\career-agent\\.venv\\Scripts\\python.exe",
      "args": ["C:\\career-agent\\mcp-career-files\\server.py"]
    }
  }
}

Absolute paths. If you installed the project elsewhere, replace C:\\career-agent with your actual path, in all occurrences. Backslashes need to be doubled — it's JSON.

Why the .venv python and not uv? Claude Desktop starts servers without loading your user PATH. Pointing directly to the virtual environment's interpreter removes the PATH dependency and makes startup faster and more predictable. uv remains the installation and test-running tool.

After saving: completely close Claude Desktop (including the icon in the system tray, next to the clock — closing the window doesn't end the process) and open it again.

To confirm, ask in the chat: "What career tools do you have?"


6. How to start

The servers are started by Claude Desktop itself — you don't need to keep anything running.

To manually verify that all three start up:

powershell -ExecutionPolicy Bypass -File .\scripts\start.ps1

Logs: C:\career-agent\logs\ (mcp-career.log, mcp-job-search.log, mcp-career-files.log).


7. How to test

powershell -ExecutionPolicy Bypass -File .\scripts\test.ps1

The script runs the pytest suite and then an end-to-end validation: module imports, initialization of the three MCPs, profile reading, score calculation, application registration, history query, and duplicate detection.

Only the unit tests:

C:\career-agent\.venv\Scripts\python.exe -m pytest tests -v

8. How to add a new job source

First of all: check if the source has a documented public API. If it requires login, cookies, or scraping, it doesn't qualify — use UnavailableJobSource and manual mode.

  1. Create the class in src/career_core/job_sources/:

from .base import IJobSource, JobQuery, SourceResult, detect_seniority

class MinhaFonteJobSource(IJobSource):
    name = "minhafonte"
    provenance = "API JSON publica de X, sem autenticacao."
    usable = True

    def search(self, query: JobQuery) -> SourceResult:
        # ... chamar a API e converter cada item em `Job`
        return SourceResult(source=self.name, jobs=jobs, ok=True, message="...")
  1. Register it in src/career_core/job_sources/registry.py:

_FACTORIES = {
    ...,
    "minhafonte": (lambda s: MinhaFonteJobSource(...), True),  # True = precisa de rede
}
  1. Enable it in .env: JOB_SEARCH_SOURCES=mock,minhafonte

  2. Add a test in tests/test_job_sources.py.

No other file in the system changes. Scoring, deduplication, and application work automatically because the source returns a normalized Job.


9. How to add a new resume

Place a .md file in C:\career-agent\data\resumes\. The filename matters: the agent automatically picks the resume whose name has the most words in common with the job.

data/resumes/
├── curriculo-principal.md      # padrao / fallback
├── curriculo-backend-dotnet.md # vence em vagas .NET/backend
├── curriculo-fullstack.md      # vence em vagas fullstack/React
└── curriculo-sap.md            # vence em vagas SAP

To force a specific one: "Prepare the application using curriculo-sap.md".


10. How to register an application

Lifecycle:

   generate_application          register_application
   (mostra o pacote)      -->    (grava o historico)
                                        |
                                        v
                                pending_approval
                                        |
                          voce aprova   |
                                        v
                                    approved
                                        |
                    VOCE se candidata no site
                                        v
                                     applied
                                        |
              +-------------+-----------+-----------+
              v             v           v           v
          interview  technical_test   offer     rejected

rejected and withdrawn are final states.

There is no path from pending_approval directly to applied. The attempt is rejected by the state machine. That's the code-level guarantee that nothing moves forward without you having seen it.


11. Example commands in Claude Desktop

Search

Procure vagas Backend .NET compativeis com meu perfil.
Priorize remoto e hibrido em Goiania.
Mostre somente vagas com score >= 80.

Analyze a pasted job

Analise esta vaga:
[cole aqui a URL e a descricao completa]

Prepare application

Prepare minha candidatura para a vaga da Nexatech.

Track

Mostre minhas candidaturas pendentes.
Quais candidaturas estao aguardando minha aprovacao?
Atualize a candidatura app-xxxx para entrevista.

Approve

Aprovo a candidatura app-xxxx.

Diagnostics

Esta tudo configurado no Career Agent?
De onde vem as vagas que voce busca?
Voce consegue se candidatar por mim no LinkedIn?

12. Current limitations

  • LinkedIn, Indeed, and Gupy work in manual mode. None of them offer a public search API for candidates. You copy the job; the agent does the rest. This is a security choice, not a pending issue.

  • Automatic coverage depends on which companies you configure. The ats source scans the public boards of companies in JOB_SEARCH_ATS_COMPANIES. The default list has 10 verified companies (~1,160 jobs), but the Brazilian market has many more — add the companies you care about.

  • Not every ATS is covered. Greenhouse, Lever, and Ashby have public endpoints. Gupy, Solides, and Kenoby don't expose public search for candidates.

  • Remotive and Arbeitnow are of limited use (measured in August 2026): Remotive returns a sample feed of 14 jobs that ignores the search parameter; Arbeitnow has 175 jobs, almost all European and on-site, zero with .NET/C#. They remain available, but outside the standard.

  • LinkedIn, Indeed, and Gupy remain in manual mode — there's no public search API for candidates, and this project doesn't automate login or scraping.

  • Requirement extraction is heuristic. It works well with bulleted descriptions; with running text, requirements come out less structured.

  • Seniority detection is keyword-based on the title and description. Ambiguous titles may come out as not_informed — report manually when it matters.

  • Salary is only compared when the job publishes the range. Most Brazilian jobs don't; in that case, the dimension stays neutral.

  • The customized resume comes out in Markdown. There's no PDF or DOCX export in V1.

  • Single-user, local installation. No multi-profile, no sync.


13. Next steps

Ordered by value/effort ratio:

  1. Export resume to PDF/DOCX — today the material comes out in Markdown and you convert it manually.

  2. Read job description from a public URL (open pages, without login), reducing copy-paste.

  3. Brazilian sources — map ATSs that expose public job listings per company and implement as IJobSource.

  4. Follow-up reminders — flag applications stuck in applied for more than N days.

  5. Pipeline metrics — response rate by score, by stack, and by modality, to calibrate weights with real data.

  6. Weight calibration — today the weights are defined in the spec; with enough history, adjust them based on what actually converts.

  7. Semantic duplicate detection — today it's by textual similarity; embeddings would catch "Backend .NET Developer" vs "C# Software Engineer".


Security

Summary of what this project does not do, by design:

Does not do

Why

Automatic LinkedIn login

violates LinkedIn ToS; risk of account ban

Store password/cookie/token

unnecessary attack surface

Automate clicks

violates LinkedIn ToS

Send applications on its own

final decision is always yours

Send messages on its own

final decision is always yours

Bypass anti-bot / CAPTCHA

illegal and disrespectful

Aggressive scraping

illegal and disrespectful

Fabricate experience

lying on a resume hurts you

Details in docs/SECURITY.md.

Claude's file access is restricted to C:\career-agent\data. It does not see C:\, nor your user folder, nor the project's own code.

F
license - not found
Not graded
quality - not tested
B
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

  • A
    license
    Not graded
    quality
    F
    maintenance
    Enables users to search for jobs, prefill applications using AI, and automate submissions across major platforms like Lever and Ashby directly from Claude or Cursor. It provides a full suite of tools for managing job queues, profile data, and resumes within a chat interface.
    34
    MIT
  • A
    license
    A
    quality
    B
    maintenance
    A personal job-search assistant for Claude Desktop that searches real job boards, scores each job 0–100 for fit, and displays a ranked board for fast triage.
    10
    79
    1
    MIT
  • F
    license
    Not graded
    quality
    C
    maintenance
    Enables running a job search with Claude Code: parses CV, discovers roles, fetches exact application fields, drafts non-trivial applications (positioning, not autofill), and renders an offline dashboard for review.
  • A
    license
    Not graded
    quality
    C
    maintenance
    Enables searching and evaluating job postings from LinkedIn and freehire.me directly through Claude Desktop. Provides tools to search jobs, fetch full posting details, and assess candidate fit using eligibility scans and a scoring rubric.
    MIT

View all related MCP servers

Related MCP Connectors

View all MCP Connectors

Latest Blog Posts

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/maraMoreir/career-agent'

If you have feedback or need assistance with the MCP directory API, please join our Discord server