visa-jobs-mcp
Identifique oportunidades de patrocínio de visto nos EUA no LinkedIn e acesse os contatos certos para acelerar seu alcance.
Documentação
visa-jobs-mcp

visa-jobs-mcp é um servidor MCP que ajuda agentes a encontrar vagas relevantes em buscas recentes do LinkedIn, com filtragem opcional ciente de visto.
Foi construído para velocidade e resultados práticos:
- buscar vagas em uma localização,
- comparar empregadores com histórico de patrocínio,
- retornar resultados acionáveis com links e informações de contato,
- manter os dados do usuário locais.
Primeiros Passos
1. Instalar no macOS (Homebrew)
brew tap neosh11/visa-jobs-mcp
brew install neosh11/visa-jobs-mcp/visa-jobs-mcp
2. Instalar no macOS/Linux (instalador bash)
curl -fsSL https://raw.githubusercontent.com/neosh11/visa-jobs-mcp/main/scripts/install.sh | bash
Fixar uma versão específica:
curl -fsSL https://raw.githubusercontent.com/neosh11/visa-jobs-mcp/main/scripts/install.sh | bash -s -- --version 0.3.1
3. Instalar no Windows (instalador PowerShell)
irm https://raw.githubusercontent.com/neosh11/visa-jobs-mcp/main/scripts/install.ps1 | iex
Fixar uma versão específica:
$env:VISA_JOBS_MCP_VERSION = "0.3.1"
irm https://raw.githubusercontent.com/neosh11/visa-jobs-mcp/main/scripts/install.ps1 | iex
4. Registrar no Codex (macOS/Linux)
codex mcp add visa-jobs-mcp --env VISA_JOB_SITES=linkedin -- visa-jobs-mcp
Registrar no Codex (Windows PowerShell):
codex mcp add visa-jobs-mcp --env VISA_JOB_SITES=linkedin -- "$env:LOCALAPPDATA\\Programs\\visa-jobs-mcp\\bin\\visa-jobs-mcp.exe"
Verificar:
codex mcp list
codex mcp get visa-jobs-mcp
5. Usar no chat
Em uma nova sessão do Codex, pergunte naturalmente:
Find IT jobs in Delhi for my skills.Set my visa preference to E3 and find software engineer jobs in New York that sponsor E3.
Compilar a partir do código-fonte (opcional)
go build -o visa-jobs-mcp ./cmd/visa-jobs-mcp
./visa-jobs-mcp --version
Se precisar atualizar data/companies.csv a partir do código-fonte, execute:
./scripts/run_internal_pipeline.sh
Nota: o runtime do MCP é somente Go. Python só é necessário para mantenedores que executam o pipeline interno de dados.
E2E ao vivo no LinkedIn (manual)
Execute uma busca real de ponta a ponta no LinkedIn (não testes simulados):
./scripts/run_live_linkedin_e2e.sh
Substituição opcional de timeout:
VISA_E2E_TEST_TIMEOUT=8m ./scripts/run_live_linkedin_e2e.sh
Parâmetros opcionais de teste ao vivo:
VISA_E2E_VISA_TYPE=E3 \
VISA_E2E_LOCATION="New York, NY" \
VISA_E2E_JOB_TITLE="Software Engineer" \
./scripts/run_live_linkedin_e2e.sh
O Que Ele Suporta
- Busca somente no LinkedIn.
- Busca geral de vagas por habilidade/localização sem necessidade de configuração de visto.
- Correspondência opcional de preferência de visto quando
preferred_visa_typesestá definido. - Sessões de busca com paginação e suporte a retomada.
- Vagas salvas e vagas ignoradas.
- Extração de contato do empregador quando disponível.
- Armazenamento local de dados privados.
- Sem uso de proxy.
- Sem chamadas de LLM dentro do runtime MCP (o agente lida com o raciocínio).
Ferramentas Principais do MCP
start_job_searchget_job_search_statusget_job_search_resultsset_user_preferencesstart_visa_job_searchget_visa_job_search_statusget_visa_job_search_resultssave_job_for_laterignore_joblist_saved_jobslist_ignored_jobsget_mcp_capabilities
Dica: peça ao agente para chamar get_mcp_capabilities primeiro para obter um contrato legível por máquina.
Contrato MCP (Gerado)
Expandir Contrato MCP (gerado automaticamente)
Gerado a partir de get_mcp_capabilities() via scripts/generate_contract_docs.py.
Servidor
server:visa-jobs-mcpversion:0.3.1capabilities_schema_version:1.2.0confidence_model_version:v1.1.0-rules-go
Necessário Antes da Busca
tool:start_job_searchrequired_fields:user_id
Decisões de Design
agent_is_reasoning_layer:Truebackground_search_runs_local_persistence:Truedata_not_shared_or_sold:Truefirst_class_job_management:Truefree_forever:Truefresh_job_search_per_query:Trueignored_companies_local_persistence:Trueignored_jobs_local_persistence:Truelicense:MITllm_api_keys_required_by_mcp:Falsellm_runtime_inside_mcp:Falseno_fake_reviews_or_bot_marketing:Trueproxies_used:Falserate_limit_backoff_retries:Truesaved_jobs_local_persistence:Truesearch_sessions_local_persistence:Truestrict_user_visa_match:Falsestrictness_modes_supported:['balanced', 'strict']supported_job_sites:['linkedin']visa_matching_optional:True
Padrões
dataset_stale_after_days:30job_db_path:data/app/visa_jobs.dbmax_scan_results:1200max_search_sessions_per_user:20rate_limit_initial_backoff_seconds:2rate_limit_max_backoff_seconds:30rate_limit_retry_window_seconds:180scan_multiplier:8search_run_ttl_seconds:21600search_session_ttl_seconds:21600strictness_mode:stricttool_call_soft_timeout_seconds:48
Ferramentas
| Ferramenta | Descrição | Entradas Obrigatórias | Entradas Opcionais |
|---|---|---|---|
get_mcp_capabilities | Retorna capacidades, ferramentas e contratos do MCP para autodescoberta do agente. | - | - |
set_user_preferences | Salva as preferências de visto do usuário para correspondência opcional específica de visto. | user_id, preferred_visa_types | - |
set_user_constraints | Salva restrições de urgência e modo de trabalho usadas para orientação personalizada. | user_id | - |
get_user_preferences | Busca as preferências e restrições salvas do usuário. | user_id | - |
get_user_readiness | Informa se o usuário e o conjunto de dados local estão prontos para a busca. | user_id | - |
find_related_titles | Retorna títulos de cargos adjacentes para ampliar buscas de baixo rendimento. | job_title | - |
add_user_memory_line | Adiciona uma linha de memória de perfil (habilidades, objetivos, receios, restrições). | user_id, content | - |
query_user_memory_blob | Consulta o bloco de memória local do usuário com filtragem de texto opcional. | user_id | - |
delete_user_memory_line | Exclui uma linha de memória por id do bloco local. | user_id, line_id | - |
save_job_for_later | Salva uma vaga na lista local do usuário para acompanhamento. | user_id | job_url, result_id, session_id |
list_saved_jobs | Lista vagas salvas em ordem cronológica reversa. | user_id | - |
delete_saved_job | Remove uma vaga salva da lista local. | user_id, saved_job_id | - |
ignore_job | Oculta uma vaga dos resultados futuros para este usuário. | user_id | job_url, result_id, session_id |
list_ignored_jobs | Lista vagas ignoradas em ordem cronológica reversa. | user_id | - |
unignore_job | Reexibe uma vaga anteriormente ignorada por id. | user_id, ignored_job_id | - |
ignore_company | Oculta todas as vagas de uma empresa em buscas futuras. | user_id | - |
list_ignored_companies | Lista empresas ignoradas em ordem cronológica reversa. | user_id | - |
unignore_company | Remove uma empresa da lista de ignoradas. | user_id, ignored_company_id | - |
mark_job_applied | Marca uma vaga como candidatado e persiste o estado do pipeline. | user_id | - |
update_job_stage | Atualiza o estágio do ciclo de vida de uma vaga rastreada (salva/candidatado/entrevista/etc). | user_id, stage | - |
list_jobs_by_stage | Lista vagas rastreadas filtradas por estágio do ciclo de vida. | user_id, stage | - |
add_job_note | Anexa ou adiciona uma nota ao registro de uma vaga rastreada. | user_id, note | - |
list_recent_job_events | Lista transições de estágio e eventos do ciclo de vida recentes. | user_id | - |
get_job_pipeline_summary | Resume as contagens do pipeline rastreado por estágio para um usuário. | user_id | - |
clear_search_session | Exclui uma sessão de busca em cache ou todas as sessões de um usuário. | user_id | - |
export_user_data | Exporta todos os registros locais de um usuário em todos os armazenamentos. | user_id | - |
delete_user_data | Exclui permanentemente todos os registros locais de um usuário. | user_id, confirm | - |
get_best_contact_strategy | Sugere o melhor canal/contato de abordagem para uma vaga. | user_id | - |
generate_outreach_message | Gera um rascunho prático de abordagem adaptado ao usuário e ao cargo. | user_id | - |
start_job_search | Inicia uma busca de vagas em segundo plano sem exigir preferências de visto. | location, job_title, user_id | - |
get_job_search_status | Consulta progresso/eventos incrementais de uma execução de busca de vagas em segundo plano. | user_id, run_id | - |
get_job_search_results | Busca a página de resultados atual de uma execução de busca de vagas em segundo plano. | user_id, run_id | - |
cancel_job_search | Solicita o cancelamento de uma execução de busca de vagas em segundo plano em andamento. | user_id, run_id | - |
start_visa_job_search | Inicia uma execução de busca em segundo plano para varreduras longas. | location, job_title, user_id | - |
get_visa_job_search_status | Consulta progresso/eventos incrementais de uma execução de busca em segundo plano. | user_id, run_id | - |
get_visa_job_search_results | Busca a página de resultados atual de uma execução de busca em segundo plano. | user_id, run_id | - |
cancel_visa_job_search | Solicita o cancelamento de uma execução em segundo plano em andamento. | user_id, run_id | - |
discover_latest_dol_disclosure_urls | Descobre as fontes mais recentes de divulgação DOL LCA/PERM. | - | - |
run_internal_dol_pipeline | Executa o pipeline interno para atualizar o conjunto de dados de empresas patrocinadoras. | - | - |
refresh_company_dataset_cache | Limpa e recarrega o cache em memória do conjunto de dados de empresas. | - | - |
Campos de Resposta da Busca
runstatusstatsguidancedataset_freshnesspaginationrecovery_suggestionsjobs[].result_idjobs[].job_urljobs[].titlejobs[].companyjobs[].locationjobs[].sitejobs[].date_postedjobs[].description_fetchedjobs[].descriptionjobs[].description_excerptjobs[].salary_textjobs[].salary_currencyjobs[].salary_intervaljobs[].salary_min_amountjobs[].salary_max_amountjobs[].salary_sourcejobs[].job_typejobs[].job_leveljobs[].company_industryjobs[].job_functionjobs[].job_url_directjobs[].is_remotejobs[].employer_contactsjobs[].visa_countsjobs[].visas_sponsoredjobs[].visa_match_strengthjobs[].eligibility_reasonsjobs[].confidence_scorejobs[].confidence_model_versionjobs[].agent_guidance
Caminhos
dataset_default:data/companies.csvignored_companies_default:data/config/ignored_companies.jsonignored_jobs_default:data/config/ignored_jobs.jsonjob_management_db_default:data/app/visa_jobs.dbpipeline_manifest_default:data/pipeline/last_run.jsonsaved_jobs_default:data/config/saved_jobs.jsonsearch_runs_store_default:data/config/search_runs.jsonsearch_session_store_default:data/config/search_sessions.jsonuser_memory_blob_default:data/config/user_memory_blob.jsonuser_preferences_default:data/config/user_preferences.json
Deprecações
build_company_dataset_from_dol_disclosures->run_internal_dol_pipeline(soft_deprecated)
JSON Bruto de Capacidades
{
"capabilities_schema_version": "1.2.0",
"confidence_model_version": "v1.1.0-rules-go",
"defaults": {
"dataset_stale_after_days": 30,
"job_db_path": "data/app/visa_jobs.db",
"max_scan_results": 1200,
"max_search_sessions_per_user": 20,
"rate_limit_initial_backoff_seconds": 2,
"rate_limit_max_backoff_seconds": 30,
"rate_limit_retry_window_seconds": 180,
"scan_multiplier": 8,
"search_run_ttl_seconds": 21600,
"search_session_ttl_seconds": 21600,
"strictness_mode": "strict",
"tool_call_soft_timeout_seconds": 48
},
"deprecations": [
{
"name": "build_company_dataset_from_dol_disclosures",
"replacement": "run_internal_dol_pipeline",
"status": "soft_deprecated"
}
],
"design_decisions": {
"agent_is_reasoning_layer": true,
"background_search_runs_local_persistence": true,
"data_not_shared_or_sold": true,
"first_class_job_management": true,
"free_forever": true,
"fresh_job_search_per_query": true,
"ignored_companies_local_persistence": true,
"ignored_jobs_local_persistence": true,
"license": "MIT",
"llm_api_keys_required_by_mcp": false,
"llm_runtime_inside_mcp": false,
"no_fake_reviews_or_bot_marketing": true,
"proxies_used": false,
"rate_limit_backoff_retries": true,
"saved_jobs_local_persistence": true,
"search_sessions_local_persistence": true,
"strict_user_visa_match": false,
"strictness_modes_supported": [
"balanced",
"strict"
],
"supported_job_sites": [
"linkedin"
],
"visa_matching_optional": true
},
"pagination_contract": {
"next_step": "use pagination.next_offset to request the next page",
"offset_model": "offset is applied to accepted jobs, not raw scraped jobs",
"result_id_aliases": "use jobs[].result_id in save_job_for_later/ignore_job to avoid URL copy friction",
"scan_behavior": "server can increase raw scan depth when auto_expand_scan=true",
"session_behavior": "pass search_session.session_id for stable paging without redundant rescans"
},
"paths": {
"dataset_default": "data/companies.csv",
"ignored_companies_default": "data/config/ignored_companies.json",
"ignored_jobs_default": "data/config/ignored_jobs.json",
"job_management_db_default": "data/app/visa_jobs.db",
"pipeline_manifest_default": "data/pipeline/last_run.json",
"saved_jobs_default": "data/config/saved_jobs.json",
"search_runs_store_default": "data/config/search_runs.json",
"search_session_store_default": "data/config/search_sessions.json",
"user_memory_blob_default": "data/config/user_memory_blob.json",
"user_preferences_default": "data/config/user_preferences.json"
},
"rate_limit_contract": {
"failure_message": "asks agent to retry shortly when the retry window is exhausted",
"max_retry_window_seconds": 180,
"retry_behavior": "automatic exponential backoff on rate-limit errors (429/Too Many Requests)"
},
"required_before_search": {
"required_fields": [
"user_id"
],
"tool": "start_job_search"
},
"search_response_fields_for_agents": [
"run",
"status",
"stats",
"guidance",
"dataset_freshness",
"pagination",
"recovery_suggestions",
"jobs[].result_id",
"jobs[].job_url",
"jobs[].title",
"jobs[].company",
"jobs[].location",
"jobs[].site",
"jobs[].date_posted",
"jobs[].description_fetched",
"jobs[].description",
"jobs[].description_excerpt",
"jobs[].salary_text",
"jobs[].salary_currency",
"jobs[].salary_interval",
"jobs[].salary_min_amount",
"jobs[].salary_max_amount",
"jobs[].salary_source",
"jobs[].job_type",
"jobs[].job_level",
"jobs[].company_industry",
"jobs[].job_function",
"jobs[].job_url_direct",
"jobs[].is_remote",
"jobs[].employer_contacts",
"jobs[].visa_counts",
"jobs[].visas_sponsored",
"jobs[].visa_match_strength",
"jobs[].eligibility_reasons",
"jobs[].confidence_score",
"jobs[].confidence_model_version",
"jobs[].agent_guidance"
],
"server": "visa-jobs-mcp",
"tools": [
{
"description": "Return MCP capabilities, tools, and contracts for agent self-discovery.",
"name": "get_mcp_capabilities",
"required_inputs": []
},
{
"description": "Save the user's visa preferences for optional visa-specific matching.",
"name": "set_user_preferences",
"required_inputs": [
"user_id",
"preferred_visa_types"
]
},
{
"description": "Save urgency and work-mode constraints used for personalized guidance.",
"name": "set_user_constraints",
"required_inputs": [
"user_id"
]
},
{
"description": "Fetch the saved user preferences and constraints.",
"name": "get_user_preferences",
"required_inputs": [
"user_id"
]
},
{
"description": "Report whether the user and local dataset are ready for search.",
"name": "get_user_readiness",
"required_inputs": [
"user_id"
]
},
{
"description": "Return adjacent role titles to widen low-yield searches.",
"name": "find_related_titles",
"required_inputs": [
"job_title"
]
},
{
"description": "Append a profile memory line (skills, goals, fears, constraints).",
"name": "add_user_memory_line",
"required_inputs": [
"user_id",
"content"
]
},
{
"description": "Query the user's local memory blob with optional text filtering.",
"name": "query_user_memory_blob",
"required_inputs": [
"user_id"
]
},
{
"description": "Delete one memory line by id from the local blob.",
"name": "delete_user_memory_line",
"required_inputs": [
"user_id",
"line_id"
]
},
{
"description": "Save a job to the user's local shortlist for follow-up.",
"name": "save_job_for_later",
"optional_inputs": [
"job_url",
"result_id",
"session_id"
],
"required_inputs": [
"user_id"
]
},
{
"description": "List saved jobs in reverse-chronological order.",
"name": "list_saved_jobs",
"required_inputs": [
"user_id"
]
},
{
"description": "Remove one saved job from the local shortlist.",
"name": "delete_saved_job",
"required_inputs": [
"user_id",
"saved_job_id"
]
},
{
"description": "Hide one job from future results for this user.",
"name": "ignore_job",
"optional_inputs": [
"job_url",
"result_id",
"session_id"
],
"required_inputs": [
"user_id"
]
},
{
"description": "List ignored jobs in reverse-chronological order.",
"name": "list_ignored_jobs",
"required_inputs": [
"user_id"
]
},
{
"description": "Unhide a previously ignored job by id.",
"name": "unignore_job",
"required_inputs": [
"user_id",
"ignored_job_id"
]
},
{
"description": "Hide all jobs from a company in future searches.",
"name": "ignore_company",
"required_inputs": [
"user_id"
]
},
{
"description": "List ignored companies in reverse-chronological order.",
"name": "list_ignored_companies",
"required_inputs": [
"user_id"
]
},
{
"description": "Remove one company from the ignored list.",
"name": "unignore_company",
"required_inputs": [
"user_id",
"ignored_company_id"
]
},
{
"description": "Mark a job as applied and persist pipeline state.",
"name": "mark_job_applied",
"required_inputs": [
"user_id"
]
},
{
"description": "Update lifecycle stage for a tracked job (saved/applied/interview/etc).",
"name": "update_job_stage",
"required_inputs": [
"user_id",
"stage"
]
},
{
"description": "List tracked jobs filtered by lifecycle stage.",
"name": "list_jobs_by_stage",
"required_inputs": [
"user_id",
"stage"
]
},
{
"description": "Attach or append a note to a tracked job record.",
"name": "add_job_note",
"required_inputs": [
"user_id",
"note"
]
},
{
"description": "List recent stage transitions and lifecycle events.",
"name": "list_recent_job_events",
"required_inputs": [
"user_id"
]
},
{
"description": "Summarize tracked pipeline counts by stage for one user.",
"name": "get_job_pipeline_summary",
"required_inputs": [
"user_id"
]
},
{
"description": "Delete one cached search session or all sessions for a user.",
"name": "clear_search_session",
"required_inputs": [
"user_id"
]
},
{
"description": "Export all local records for a user across stores.",
"name": "export_user_data",
"required_inputs": [
"user_id"
]
},
{
"description": "Permanently delete all local records for a user.",
"name": "delete_user_data",
"required_inputs": [
"user_id",
"confirm"
]
},
{
"description": "Suggest best outreach channel/contact for a job.",
"name": "get_best_contact_strategy",
"required_inputs": [
"user_id"
]
},
{
"description": "Generate a practical outreach draft tailored to user and role.",
"name": "generate_outreach_message",
"required_inputs": [
"user_id"
]
},
{
"description": "Start a background job search without requiring visa preferences.",
"name": "start_job_search",
"required_inputs": [
"location",
"job_title",
"user_id"
]
},
{
"description": "Poll incremental progress/events for a background job search run.",
"name": "get_job_search_status",
"required_inputs": [
"user_id",
"run_id"
]
},
{
"description": "Fetch current result page from a background job search run.",
"name": "get_job_search_results",
"required_inputs": [
"user_id",
"run_id"
]
},
{
"description": "Request cancellation of an in-progress background job search run.",
"name": "cancel_job_search",
"required_inputs": [
"user_id",
"run_id"
]
},
{
"description": "Start a background search run for long scans.",
"name": "start_visa_job_search",
"required_inputs": [
"location",
"job_title",
"user_id"
]
},
{
"description": "Poll incremental progress/events for a background search run.",
"name": "get_visa_job_search_status",
"required_inputs": [
"user_id",
"run_id"
]
},
{
"description": "Fetch current result page from a background search run.",
"name": "get_visa_job_search_results",
"required_inputs": [
"user_id",
"run_id"
]
},
{
"description": "Request cancellation of an in-progress background run.",
"name": "cancel_visa_job_search",
"required_inputs": [
"user_id",
"run_id"
]
},
{
"description": "Discover latest DOL LCA/PERM disclosure sources.",
"name": "discover_latest_dol_disclosure_urls",
"required_inputs": []
},
{
"description": "Run internal pipeline to refresh sponsor-company dataset.",
"name": "run_internal_dol_pipeline",
"required_inputs": []
},
{
"description": "Clear and reload in-memory company dataset cache.",
"name": "refresh_company_dataset_cache",
"required_inputs": []
}
],
"version": "0.3.1"
}
Regenere esta seção e o bloco de contrato do site com:
python3 scripts/generate_contract_docs.py
Valide se os blocos gerados estão atualizados:
python3 scripts/generate_contract_docs.py --check
CLI Manual (opcional)
Verifique a versão do binário:
visa-jobs-mcp --version
Execute o servidor MCP diretamente (para depuração):
visa-jobs-mcp
Execute o pipeline interno DOL (fluxo de mantenedor, a partir do checkout do código-fonte):
./scripts/run_internal_pipeline.sh
Solução de Problemas
- Se a busca não retornar vagas, continue consultando
get_visa_job_search_statuse chameget_visa_job_search_resultsnovamente para o mesmorun_id. - Se ocorrerem limites de taxa upstream, aguarde alguns minutos e tente novamente.
- Se a instalação via Homebrew falhar devido a artefatos de release ausentes, tente novamente após a conclusão dos fluxos de release.
Dados e Privacidade
- Os dados são armazenados localmente por padrão.
- Sem telemetria ou venda de dados externos.
- A correspondência de patrocínio usa
data/companies.csve saídas do pipeline baseado em DOL.
Para Mantenedores
- Repositório tap do Homebrew:
https://github.com/neosh11/homebrew-visa-jobs-mcp - Guia do colaborador:
AGENTS.md - Fluxo de release:
.github/workflows/build-release-binaries.yml - Build local de artefato de release:
./scripts/build_release_binaries.sh(binário Go nativo +data/companies.csvincluído)
Licença
MIT. Consulte LICENSE.