PersonalKnowHow

Transforma seu histórico do LinkedIn/GitHub/cursos em um grafo de conhecimento consultável via MCP, usando busca semântica real em vez de correspondência por palavras-chave.

Documentação

PersonalKnowHow

Entre na lista de espera · Demonstração ao vivo · Problemas

Transforma um histórico pessoal de aprendizado/trabalho disperso — LinkedIn, GitHub, plataformas de cursos, e-mails de conclusão do Gmail, repositórios de projetos relacionados — em um grafo de conhecimento unificado, consultável com busca semântica em vez de correspondência por palavras-chave. Execute localmente com seus próprios dados em dois comandos, sem necessidade de conta — ou consulte os servidores MCP reais e implantados descritos abaixo.

PersonalKnowHow answering a job-fit question against the graph

Pedindo ao Claude (via o servidor MCP implantado) para avaliar uma vaga de emprego em relação ao grafo — evidência real extraída do histórico do LinkedIn/GitHub, não um palpite. (vídeo em resolução completa)

Experimente localmente em 60 segundos

Sem conta Cloudflare, sem cadastro, nada implantado — apenas sua própria máquina.

git clone https://github.com/Georgi-Petkov/personalknowhow.git
cd personalknowhow
python quickstart.py
python ingest/query_local.py "what do I know about X"

quickstart.py detecta automaticamente quaisquer fontes já disponíveis na sua máquina e pula o restante com um motivo claro — no mínimo, uma CLI do GitHub já autenticada (gh auth login) ou seus repositórios de projetos relacionados são suficientes para obter resultados reais. query_local.py incorpora seu grafo com um pequeno modelo local (BAAI/bge-small-en-v1.5 via sentence-transformers, baixado uma vez do Hugging Face na primeira execução — a única dependência real de rede do modo local, distinta de precisar de uma conta na nuvem) e classifica os resultados por similaridade de cosseno, a mesma abordagem que os servidores MCP implantados usam.

Quer seu próprio histórico do LinkedIn no grafo, não apenas evidências do GitHub/projetos locais? Solicite sua exportação em linkedin.com → Configurações e privacidade → Privacidade de dados → Obtenha uma cópia dos seus dados, depois:

python quickstart.py --linkedin ~/Downloads/LinkedInDataExport.zip
python ingest/query_local.py "what do I know about X"

quickstart.py cuida de descompactar e rotear para o script de ingestão correto — sem posicionamento manual de arquivos, sem flags para descobrir. (Solicitar a exportação acontece inteiramente no site do LinkedIn e pode levar alguns minutos para eles prepararem — tudo depois disso são os dois comandos acima.)

Cada outra fonte (edX, DataCamp, Gmail) precisa de sua própria configuração única (um arquivo JSON preenchido manualmente ou credenciais OAuth) — quickstart.py detecta e pula cada uma graciosamente com um motivo de uma linha se não estiver configurada; veja ingest/CLAUDE.md para detalhes por fonte se quiser adicionar uma.

Experimente a demonstração ao vivo

https://personalknowhow-demo.kxtwrdzt6g.workers.dev/mcp é um servidor MCP real e implantado — mas não é uma página web. Abrir essa URL em um navegador envia um GET simples, e servidores MCP só falam POST com enquadramento JSON-RPC, então você verá apenas um {"error":{"message":"Method not allowed."}} puro. Isso é esperado, não está quebrado — significa que você está olhando do jeito errado.

A maneira real de usá-lo é como um conector MCP. No Claude Desktop, edite claude_desktop_config.json (localização do arquivo de configuração):

{
  "mcpServers": {
    "personalknowhow-demo": {
      "command": "npx",
      "args": ["mcp-remote", "https://personalknowhow-demo.kxtwrdzt6g.workers.dev/mcp"]
    }
  }
}

Reinicie o Claude Desktop e pergunte algo como "use personalknowhow-demo para verificar se tenho experiência com Django" — o Claude chama a ferramenta query_knowhow via MCP e recebe evidências com correspondência semântica (cursos, projetos, certificações) com pontuações de similaridade, sem necessidade de autenticação.

Se você só quiser confirmar que o servidor está ativo sem configurar um cliente:

curl -s https://personalknowhow-demo.kxtwrdzt6g.workers.dev/mcp \
  -X POST -H "Content-Type: application/json" -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test","version":"1.0"}}}'

Um 200 com uma resposta JSON-RPC confirma que está ativo — o cabeçalho Accept acima é obrigatório; sem ele, o servidor retorna corretamente 406 Not Acceptable, que é um erro diferente, também esperado, do GET do navegador acima.


Por que isso existe

Listas de conclusão de cursos e currículos com correspondência por palavras-chave são um sinal fraco do que alguém realmente sabe. Este projeto constrói um grafo de conhecimento real a partir de fontes primárias (não resumos autorrelatados), incorpora cada entrada com um modelo de incorporação real e o expõe como uma ferramenta MCP consultável — então "tenho experiência com Django?" é respondido percorrendo evidências reais (o README de um projeto, uma conclusão de curso, um endosso) com uma pontuação de similaridade anexada, não um palpite.

Arquitetura

ingest/            Source-specific scripts → common schema
                    {title, type, provider, date, description, domain_tags}
corpus/             Generated markdown, one subfolder per source (not tracked — see Privacy below)
graph.json          Extracted nodes/edges from corpus/ (not tracked)
mcp/                Public MCP server (Cloudflare Worker) — semantic search, no auth
mcp-private/        Private MCP server — same search, bearer-token gated, adds
                    signal-only evidence (job applications, career interests)

Fontes de ingestão: LinkedIn (via a https://learn.microsoft.com/en-us/linkedin/dma/member-data-portability/overview, apenas para a UE — veja docs/linkedin-connector-notes.md para notas sobre a alternativa de exportação manual para outras regiões), GitHub (via a CLI gh, excluindo forks — um fork é evidência de navegação, não de construção), conclusões de cursos DataCamp/edX/Skilljar, Gmail (e-mails de conclusão de outras plataformas) e repositórios de projetos relacionados (descobertos automaticamente, evidenciados via README + nomes de arquivos rastreados + uma passagem de palavras-chave, não autorrelatados).

ingest/merge.py deduplica entre fontes (idempotente — seguro para reexecutar). ingest/build_graph.py extrai nós/arestas do frontmatter corpus/ para graph.json.

A camada RAG

Tanto mcp/ quanto mcp-private/ são Cloudflare Workers sem estado (createMcpHandler, sem Durable Object) que incorporam cada entrada do corpus com Workers AI (@cf/baai/bge-base-en-v1.5, 768-dim) no momento da exportação e incorporam a string de consulta no momento da solicitação, depois classificam por similaridade de cosseno. Duas ferramentas MCP são expostas: query_knowhow(topic) para busca semântica e list_by_type(type) para uma listagem simples. O servidor privado adicionalmente marca cada resultado com um evidence_tier (demonstrated vs. signal_only), para que uma candidatura de emprego ou entrada de interesse de carreira nunca possa ser confundida com prova de uma habilidade.

Design de privacidade

corpus/ e graph.json nunca são públicos — nenhum código voltado ao público os lê diretamente. A única fonte de dados pública sancionada é mcp/public_entries.json, construída por ingest/build_public_export.py via uma lista de permissões com falha fechada: apenas categorias de corpus explicitamente listadas (cursos, projetos, certificações, educação, endossos, cargos, perfil, recomendações, artigos) são exportadas. Uma nova categoria de corpus é excluída por padrão até que alguém a adicione deliberadamente à lista de permissões — a mesma disciplina que mantém candidaturas de emprego e dados de interesse de carreira fora do servidor público inteiramente; esses dados só existem em mcp-private/, protegidos por um token de portador, e nunca são commitados neste repositório também (veja .gitignore).

Ferramentas de agente de carreira

Uma segunda camada construída sobre o mesmo corpus: ingest/analyze_job_postings.py pontua vagas de emprego raspadas contra a cobertura de habilidades conhecida usando as mesmas incorporações (similaridade graduada known/peripheral, não correspondência binária por palavras-chave), ingest/cv_tailor.py corresponde os requisitos de uma vaga contra bullets de currículo com um sistema explícito de dois níveis (correspondências de termo exato vs. correspondências semanticamente relacionadas, estas últimas sempre rotuladas como "verificar antes de afirmar" em vez de assertivas), e ingest/recommend_courses.py cruza catálogos de cursos contra lacunas de cobertura.

Executando fontes de ingestão individuais manualmente

python quickstart.py (veja o topo deste README) executa tudo abaixo automaticamente para quaisquer fontes que detectar. Para controle mais fino — uma única fonte, flags não padrão ou reexecutar apenas uma etapa após uma mudança no corpus — execute qualquer um destes diretamente:

pip install -r requirements.txt

# Run a specific ingest source, e.g.:
python ingest/github_ingest.py
python ingest/linkedin_api_ingest.py --domains PROFILE,POSITIONS,SKILLS

# Deduplicate corpus after any ingest run
python ingest/merge.py

# Build graph.json from corpus/
python ingest/build_graph.py

Cada script ingest/*_ingest.py é independente — execute as fontes que se aplicam a você. Todos escrevem markdown em corpus/<source>/ usando o esquema compartilhado abaixo.

Esquema do corpus

Cada arquivo markdown em corpus/ usa este frontmatter YAML:

---
title: "Advanced Python Programming"
type: "course"              # course | certification | position | project | education | ...
provider: "LinkedIn Learning"
date: "2024-01-15"
description: "Free-text summary."
domain_tags:
  - python
  - programming
---

Implante seu próprio servidor MCP hospedado (opcional, precisa de uma conta Cloudflare)

O modo local (acima) é suficiente para consultar seu próprio grafo — esta seção é apenas para hospedá-lo como um servidor MCP real ao qual outros clientes/pessoas possam se conectar, da mesma forma que a demonstração ao vivo funciona.

cd mcp && npm install && npm run deploy        # public server
cd mcp-private && npm install && npm run deploy # private server
cd mcp-private && npm run secret                # set PRIVATE_MCP_TOKEN

Ambos precisam de uma conta Cloudflare com acesso ao Workers AI (binding [ai], remote = true em wrangler.toml). Reconstruindo as incorporações após uma mudança no corpus:

CLOUDFLARE_ACCOUNT_ID=... CLOUDFLARE_AI_TOKEN=... python ingest/build_public_export.py
CLOUDFLARE_ACCOUNT_ID=... CLOUDFLARE_AI_TOKEN=... python ingest/build_private_export.py

Adicionando uma nova fonte de ingestão

  1. Crie ingest/<source>_ingest.py que lê a exportação bruta e escreve arquivos markdown em corpus/<source>/ usando o esquema acima.
  2. merge.py e build_graph.py não exigem mudanças — eles escaneiam corpus/ genericamente.
  3. Se a nova categoria deve ser pública algum dia, adicione-a deliberadamente a ALLOWLIST em ingest/build_public_export.py — ela é excluída por padrão caso contrário.