Servidor MCP
O servidor Power Portals Pro MCP oferece aos assistentes de programação de IA conhecimento direto desse framework enquanto você constrói. É um servidor Model Context Protocol , vem junto com o framework, e não há chave de licença nem nada para se inscrever.
Por que ela existe
Duas coisas que um agente não consegue obter apenas com a documentação, e ambas causam código quebrado:
- A superfície da API é grande demais para lembrar. Várias centenas de componentes em ambas as pilhas, cada um com dezenas de parâmetros. Um agente que meio que lembra um nome de parâmetro escreve algo plausível que não compila — ou pior, compila e não faz nada.
- Seu Dataverse não está em nenhum documento. Nomes lógicos de tabelas e colunas, nomes de esquemas de relacionamento, valores de conjunto de opções e — acima de tudo — GUIDs de visualização salva existem apenas no seu ambiente. Todo exemplo de código neste site escreve um id de visualização como uma reticente, porque não há mais nada que ele possa escrever.
O que ela responde
- O framework — a referência completa de parâmetros e prop para cada componente em ambas as pilhas com tipos, padrões e valores permitidos; amostras completas de trabalho retiradas literalmente deste site; os guias; as convenções de
AGENTS.md; e a matriz de paridade Blazor-para-React. Ela é compatível com versões com os pacotes que você instalou. - Seu ambiente, somente leitura — as tabelas e colunas que você realmente tem, para quais editores cada coluna mapeia, nomes de relacionamentos, valores de conjunto de opções e suas visualizações salvas com seus GUIDs reais.
Nota
Toda ferramenta do Dataverse lê metadados. Nenhuma delas lê, grava ou deletura um registro, então apontar um agente para um ambiente de produção permite que ele aprenda a forma dos seus dados sem poder mexer neles.
Adicioná-lo a um projeto
Dois lugares onde pode viver
Há aqui um jogo de ovo e galinha que vale a pena ser explícito. Os templates escrevem a configuração no projeto que criam — mas o servidor é mais útil antes mesmo que esse projeto exista, quando você está escolhendo um template e suas opções. Então instale-o uma vez para você e deixe o arquivo por projeto assumir a partir daí.
Uma vez por máquina, para qualquer pasta
Isso torna o servidor disponível em todos os lugares, inclusive em uma pasta vazia que você está prestes a instalar. Ele pode então responder qual template usar, o que significam as opções e o que configurar depois. Deliberadamente desfixado, para rastrear a versão mais recente:
claude mcp add --scope user powerportalspro -- dnx PowerPortalsPro.Mcp --yes
O Visual Studio lê um nível .mcp.json de usuário da sua pasta de perfil, o Cursor usa ~/.cursor/mcp.json, e o VS Code tem uma configuração MCP em nível de usuário em suas configurações. Cada um ocupa o mesmo servers bloco.
Por projeto, fixado em sua versão
Projetos criados a partir dos templates do Power Portals Pro já estão conectados por cabo: o template escreve a .mcp.json na raiz da solução, fixado na versão correspondente do servidor. Não há nada a fazer.
Para adicioná-lo a um projeto existente, execute isso na pasta do projeto — ele escreve o mesmo .mcp.json para você:
claude mcp add --scope project powerportalspro -- dnx PowerPortalsPro.Mcp --yes
Note o que isso não faz: deixa o servidor sem fixação, então a pasta recebe o servidor publicado mais novo em vez daquele que corresponde aos PowerPortalsPro.* pacotes referenciados pelo seu projeto. Esse é o padrão correto para um projeto que acompanha a versão atual, e o padrão errado para um projeto deliberadamente mantido em uma versão antiga — fixe anexando a versão, como os templates fazem:
claude mcp add --scope project powerportalspro -- dnx PowerPortalsPro.Mcp@8.0.0 --yes
Ou escreva o arquivo você mesmo, na raiz da sua solução:
{
"servers": {
"powerportalspro": {
"type": "stdio",
"command": "dnx",
"args": [ "PowerPortalsPro.Mcp", "--yes" ]
}
}
}
Qual arquivo seu editor lê
Visual Studio 2022 17.14+ e Visual Studio 2026 lêem
.mcp.jsonda pasta de solução, assim como o Claude Code. VS Code lê.vscode/mcp.jsone Cursor lê.cursor/mcp.json— ambos usam o mesmoserversbloco, então copie para ele.
dnx vem com o SDK .NET 10, que você já tem: todo projeto Power Portals Pro é hospedado por ASP.NET Core, incluindo os SPAs React. A primeira execução baixa o pacote e o armazena em cache.
Ter ambos é a configuração pretendida. As duas entradas usam o mesmo nome de servidor, então um cliente que entende ambos os escopos usa o do projeto — o que significa que você recebe as respostas combinadas dentro de um projeto, e as mais recentes em qualquer outro lugar.
O comando ppp-mcp, se você quiser
Os comandos do terminal nesta página — login, status, logout e os demais — são executados dnx sem nada instalado: dnx PowerPortalsPro.Mcp login. Se preferir digitar ppp-mcp login, instale o pacote como uma ferramenta global .NET:
dotnet tool install --global PowerPortalsPro.Mcp
Isso coloca ppp-mcp no seu PATH: o SDK .NET normalmente adiciona sua pasta global tools — %USERPROFILE%\.dotnet\tools no Windows, ~/.dotnet/tools macOS e Linux — a ele. Se o comando não for encontrado, abra um novo terminal; se ainda não for, adicione essa pasta a PATH você mesmo.
Uma ferramenta global permanece na versão que você instalou, onde dnx busca a mais recente, então atualize conforme descrito abaixo. Seu cliente MCP pode continuar lançando o servidor de dnx qualquer forma: ambos lendo as mesmas ligações de pasta e os mesmos logins salvos.
Conferindo se está funcionando
Pergunte ao seu assistente algo que só o servidor pode responder — por exemplo: "use get_component_api para me mostrar todos os parâmetros no MainGrid". Se a ferramenta não estiver disponível, o cliente não pegou o arquivo de configuração; a maioria precisa de um reinício após a adicionação.
Atualização
Como você atualiza depende de como você instalou.
- Instalado com
dnx, unpinned — a entrada para toda a máquina acima — não precisa de nada rodado.dnxresolve a versão mais recente dos seus feeds NuGet toda vez que seu cliente inicia o servidor, então uma nova versão chega na próxima vez que você reiniciar o cliente. - Fixado no arquivo de um projeto
.mcp.json. Os templates escrevemPowerPortalsPro.Mcp@<version>, correspondendo aos pacotes de framework que o projeto usa. Mude essa versão quando você atualizar os pacotes, para que as respostas continuem descrevendo o framework que o projeto realmente roda.
Instalado como uma ferramenta global (dotnet tool install --global PowerPortalsPro.Mcp, que coloca ppp-mcp em seu PATH):
dotnet tool update --global PowerPortalsPro.Mcp
Importante
Feche seu cliente MCP primeiro. Um servidor em execução mantém seus próprios arquivos abertos, e a atualização falha com o acesso ao caminho ... é negado até que nada os esteja usando. Inicie o cliente novamente depois para carregar a nova versão.
Conectando-se ao Dataverse
As ferramentas de documentação não precisam de configuração alguma. As ferramentas de metadados precisam de uma conexão com seu ambiente, e essa conexão pertence à pasta, não à máquina. Execute isso uma vez no projeto:
dnx PowerPortalsPro.Mcp login
Os ambientes pertencem à pasta
Isso vincula essa pasta a um ambiente. Se você trabalha entre vários clientes, cada projeto permanece conectado em seus próprios ambientes e agentes em pastas diferentes nunca se cruzam. Isso é o que pac auth select não pode fazer — ele troca um único perfil de máquina inteira, então mudar o cliente em um lugar muda tudo em todos os lugares.
O login usa o fluxo de código do dispositivo por padrão, então funciona via SSH, dentro de um container e em WSL, e você pode finalizar no celular. Passe --browser se preferir abrir um.
Vários ambientes em uma mesma pasta
Uma pasta pode ser logada em vários ambientes ao mesmo tempo — como os ambientes de desenvolvimento, teste e produção do cliente. Cada login uma com outro ambiente adiciona à lista da pasta e --name dá o nome pelo qual você vai se referir:
dnx PowerPortalsPro.Mcp login --environment https://contoso-dev.crm.dynamics.com --name dev
dnx PowerPortalsPro.Mcp login --environment https://contoso-test.crm.dynamics.com --name test
dnx PowerPortalsPro.Mcp login --environment https://contoso.crm.dynamics.com --name prod
O primeiro ambiente é o primário, e toda ferramenta age sobre ele, a menos que você peça outra: "listar as opiniões sobre contato no teste" é respondido a partir de test, e a próxima pergunta volta para a primária. Passe --make-primary para login adicionar um ambiente como primário, ou peça para seu assistente reordená-las.
Toda resposta que tocou o Dataverse começa nomeando o ambiente de onde veio — seu nome, sua posição e sua URL — então uma mudança feita em produção nunca se lê igual a uma feita em desenvolvimento.
Onde as coisas são armazenadas
- A vinculação —
.ppp/mcp.jsonna pasta. Lista os ambientes em ordem, com nome e conta para cada um, não guarda segredos e é seguro para comprometer: um colega de equipe que clona o repositório é apontado para os ambientes corretos sem ser informado. - Seu token — mantido no seu perfil de usuário e criptografado pelo keystore do sistema operacional (DPAPI no Windows, Keychain no macOS, libsecret no Linux). Ele nunca é escrito no repositório. Se nenhuma keystore estiver disponível, o log-in recusa em vez de deixar um token de atualização no disco limpo.
O cache de tokens é codificado pelo ambiente, então um segundo clone do repositório do mesmo cliente não pede para você fazer login novamente, enquanto um cliente diferente sempre faz login — e assim como cada ambiente que você adiciona a uma pasta.
Comandos
Execute-os como dnx PowerPortalsPro.Mcp <command>, ou como ppp-mcp <command> se você tivesse instalado a ferramenta global. Todos esses ativos atuam na pasta atual, a menos que você passe --workspaceem .
login— faça login e vincule um ambiente a essa pasta, após qualquer uma já vinculada. Opções:--environment <url>,--name <name>,--pac-profile <name>--make-primary, ,--username <upn>,--tenant <id>, , .--browserNomeie um ambiente que já esteja vinculado —--environment test— para iniciar login nele novamente.status— quais ambientes essa pasta usa e qual é a primária, de onde cada uma veio, qual conta está armazenada em cache e se cada conexão funciona.logout— remover um ambiente dessa pasta:--environment <name>para um,--allpara cada um. Adicionar--forgetpara remover o login salvo também.environments— listar os perfis de CLI do Power Platform disponíveis para espelhar.azure—azure login, ,statuselogoutsubscriptions: vincula essa pasta a uma assinatura do Azure para as ferramentas de implantação.
Outras formas de se conectar
O ambiente e as credenciais são resolvidos nesta ordem, então a declaração de intenção mais explícita vence:
- Variáveis de ambiente —
PPP_D365_URL,PPP_D365_CLIENT_IDePPP_D365_CLIENT_SECRETno blocoenvdo servidor. Um principal de serviço, e a forma de conectar isso em CI ou em um contêiner compartilhado.PPP_D365_URLtorna-se o ambiente primário, antes de qualquer um ao qual a pasta está vinculada, e o principal de serviço é usado apenas para o principal. - O login da pasta — escrito por
login. O caminho normal. - As próprias configurações do projeto — as mesmas
D365:Url,D365:ClientIdeD365:ClientSecret(ouD365:Secret) o próprio portal lê dos secretos de usuário eappsettings. Um projeto Power Portals Pro configurado, portanto, muitas vezes não precisa de login algum.
Perfis de CLI do Power Platform
Se você já mantém ambientes em pac, pode começar de um em vez de procurar uma URL:
dnx PowerPortalsPro.Mcp environments
dnx PowerPortalsPro.Mcp login --pac-profile "Acme Dev"
A CLI não tem um comando que forneça um token de acesso, e mantém as credenciais em seu próprio armazenamento, então sua sessão não pode ser reutilizada diretamente. O que --pac-profile faz é pegar o ambiente e a conta de um perfil e entrar como essa conta — geralmente sem ser solicitado, porque você já tem uma sessão.
Nota
O próprio perfil ativo da CLI nunca é alterado.
pac auth selecté deliberadamente não utilizado: ele moveria todos os projetos de uma vez.
As ferramentas
Raramente é necessário nomear uma ferramenta — os assistentes escolhem a partir das descrições — mas ajuda saber o que está lá.
Documentação, sempre disponível
find_parity Whether a component exists on the other stack
get_component_api Every parameter or prop, with types, defaults and permitted values
get_conventions The golden rules from AGENTS.md
get_doc One documentation section in full
get_example A complete working sample, verbatim
get_page_recipe Guide, both stacks' samples and API links for one topic
list_components Browse what the framework ships
search_docs Open questions across the guides, API reference and samples
whats_new Release notes
Seu ambiente, uma vez conectado
describe_table Columns, and the editor each one maps to
list_choices Option-set values and labels
list_relationships Schema names for SubGrid and ManyToManyLookupEdit
list_tables Find a table's logical name
list_views Saved views with their real GUIDs
Escolha entre ambientes
Toda ferramenta que chega ao Dataverse pega um nome opcional environment — um nome como test, uma posição como 2, ou a URL — e usa o principal sem um. Um nome que não corresponde a nada é recusado junto com a lista de ambientes que existem, nunca correspondendo ao mais próximo.
dataverse_status Every environment this folder has, which is the primary, and whether each connects
remove_environment Stop this folder reaching an environment
link_environment_slot Tie an environment to an App Service deployment slot
rename_environment Call an environment what you call it: dev, test, prod
set_environment_index Reorder the environments; position 1 is the primary
Adicionar um ambiente exige login, então só login faz isso. O resto seu assistente pode fazer quando você pedir. Mover um ambiente para a posição 1 muda onde toda escrita posterior é feita por padrão, então set_environment_index pergunta primeiro quando mudaria o primário, e remove_environment sempre pergunta.
Os próprios discos
Os metadados indicam qual é a forma; eles dizem o que realmente está nela — qual valor de conjunto de opções uma linha realmente carrega, se uma busca está preenchida, se a linha que seu código acabou de escrever saiu certa. Um agente que não consegue olhar vai adivinhar.
get_record One row by id, a column per line so a wide record stays readable
read_records A page of any table, or anything FetchXML can express
Ler é como você — o principal do serviço ou o usuário logado, nunca um usuário do portal. Nenhuma das permissões de tabela, colunas ou filtros de linha do portal se aplica, então isso mostra o que está no ambiente e não o que um determinado usuário do portal seria mostrado. O FetchXML de uma visualização salva roda literalmente.
Colocando um novo projeto em andamento
check_setup What this folder still needs before the portal will start
get_setup_plan The steps to a running portal, and what each one needs
get_setup_script A reviewable script that performs them, with your values filled in
get_upgrade_plan Moving to a newer release: what breaks, and which files name a version
get_upgrade_plan é a que deve ser chamada antes de mudar uma string de versão. Ele lê a versão referenciada por esse projeto, calcula quais releases ficam entre essa e o alvo, e retorna todas as mudanças que quebram nelas com suas instruções de migração — junto com os arquivos que nomeiam uma versão, incluindo o pin .mcp.json do servidor que nada mais detectaria. Remover os pacotes sem ele gera erros de build cuja causa várias versões atrás.
A solução gerenciada
O framework precisa PowerPortalsProCore ser instalado antes que um portal seja executado, e PowerPortalsProLocalization se você localizar. Esses arquivos buscam uma versão e a importam sem a CLI do Power Platform, então o ambiente que eles alcançam é aquele ao qual essa pasta está vinculada, e não a pac que está apontada.
get_solution_import_status How an import started by install_solution is going
install_solution Download a managed solution and import it
list_solutions What is installed, and which releases are available
publish_customizations Make pending maker-portal changes live
Uma importação é de longa duração, então install_solution inicia e devolve um ID de trabalho; get_solution_import_status reporta o progresso e o resultado, com a própria mensagem do Dataverse quando falha.
Nota
publish_customizationsé a mesma ação que Publicar todas as personalizações no portal maker, então ele publica tudo que estiver pendente no ambiente, não apenas suas próprias mudanças — em um ambiente de desenvolvimento compartilhado que pode fazer o trabalho inacabado de um colega funcionar. Não é necessário depoisinstall_solution: importar uma solução gerenciada publica o que ela traz.
Sua própria solução
As alterações que o servidor faz em um ambiente — um papel de segurança criado, um privilégio concedido ou recuperado — vão para uma solução sua, registrada para aquele ambiente em .ppp/mcp.json. create_solution configure o publisher e a solução uma vez, no ambiente que você construiu; até que uma seja registrada, as ferramentas que personalizam o Dataverse recusam, porque uma alteração feita fora de uma solução fica presa na solução Padrão, onde nada pode exportá-la.
configure_solution Record an existing solution, or change how it exports
create_solution A publisher and an unmanaged solution, recorded for the environment
describe_solution The recorded solution, its version and what it holds
export_solution Save it under solutions/, managed or unmanaged as recorded
get_solution_export_status Finish an export that took longer than the tool waits
push_solution Export it and import it into another of the folder's environments
O binding também registra se a solução viaja sem gerenciamento (padrão, para ambientes que também são trabalhados) ou gerenciada (para ambientes que apenas recebem). export_solution Levanta a última parte da versão e salva o zip no workspace, push_solution exporta e importa para outro ambiente vinculado à mesma pasta — build in dev, push to test e production. Uma solução que depende do próprio Power Portals Pro não importa até que o destino tenha essa pasta também.
Funções no portal
Um papel de portal é metade código e metade dados. O desenvolvedor decide o que o nome "Dealer" concede; um administrador decide quem o detém; nada une os dois além da cadeia. Esses mantêm a metade do Dataverse do mesmo local onde a AddPortalRole chamada é escrita.
create_portal_role A role for an AddPortalRole registration to bind to
create_portal_role_configuration Decide which new users are given a role
delete_portal_role Remove a role, and every assignment of it
delete_portal_role_configuration Stop giving a role to new users, leaving the role in place
list_portal_roles The roles, and which of them new users start with
update_portal_role Rename, describe, or activate/deactivate a role
update_portal_role_configuration Change which new users are given a role
A string é toda a junção. Um erro de digitação entre o registro e o registro gera um papel que é registrado, atribuível e não concede nada — sem erro em lugar algum. Deixar o agente que acabou de escrever o registro criar o registro correspondente fecha essa lacuna e check_setup detecta as incompatibilidades já existentes: ele compara todos os nomes de função escritos no projeto com os registros e reporta os que estão faltando ou inativos.
Uma linha de Configuração de Função do Portal decide quais usuários recém-registrados recebem uma função: cada um deles, ou aqueles que correspondem aos critérios do FetchXML. Os critérios são verificados contra as regras que o portal aplica antes da linha ser escrita, porque o portal falha no fechamento por critérios ruins e uma regra quebrada parece exatamente uma regra que não correspondeu corretamente a ninguém. Os administradores editam as mesmas linhas na página de Configuração de Função do portal.
Nota
Deletar um papel joga fora todas as atribuições dele e nada lembra quem o detinha. Desativar não concede nada e não cria reivindicação também, mas mantém as atribuições, então é a forma reversível de desligar um papel. Ambas as ferramentas de exclusão pedem que você confirme primeiro.
Sites licenciados
Um registro do site Power Portals Pro é o que licencia um portal servido a partir de uma determinada URL. Esses registros listam, adicionam e mantêm — normalmente uma vez por ambiente, e novamente quando um portal se move para seu host de produção.
create_portal_website Licence a new URL
delete_portal_website Remove the record, and the licence with it
list_portal_websites The URLs licensed here, and whether each has a key
update_portal_website Correct a URL, set a new key, or deactivate one
Essa é a primeira coisa a verificar quando cada endpoint retorna 402. Sem um registro ativo correspondente, cada endpoint de dados naquele host recusa a solicitação. Deletar um registro leva a licença a partir da próxima solicitação, então prefira desativar enquanto você investiga; a exclusão pede que você confirme.
Azure deployment
A maioria dessas ferramentas apenas lê. Essas só precisam de Reader na assinatura, e respondem às perguntas que custam dias às pessoas. check_deployment é a única a saber: ele compara o que o projeto precisa com o que o App Service realmente tem, e nomeia a falha — uma configuração obrigatória que só existiu nos seus segredos de usuário, o ambiente deixado no Desenvolvimento, WebSockets desligados em um portal Blazor, um registro do site do portal que não cobre o host implantado, um portal que não pode acessar o Dataverse.
azure_status Which subscription this folder deploys to, and whether it connects
check_deployment What the project needs vs. what is actually deployed
configure_app_service Apply the recommended platform settings to an existing app
create_app_service Resource group, plan and web app, configured for your stack
create_deployment_slot A slot that runs against one of your environments, linked to it
deploy_to_app_service Build with dotnet publish and push the result
describe_app_service One app's platform configuration and setting names
enable_app_service_logging Send an app's logs to a workspace of its own, kept 60 days
get_deployment_plan The steps, and every plan tier with its current price
list_app_services The web apps in the subscription
list_deployment_slots The slots, the environment each runs against, and the links
restart_app_service Restart the web app, after confirming
set_app_service_settings Merge application settings
swap_slots Promote a slot's build, each slot keeping its own environment
Sete ferramentas alteram o App Service: , , , , , e create_deployment_slot swap_slots. Cada uma delas pede que você confirme e informa quanto custará antes de você responder — o valor real mensal para sua região, lido da lista pública de preços do Azure, com uma nota de que a lista de varejo ignora qualquer Acordo Empresarial ou reserva que você tenha. Novos recursos adotam por padrão o nível mais barato que pode se manter aquecido, para qualquer ambiente, incluindo produção, considerando que escalar depois é um minuto e o excesso de provisionamento é um projeto que ninguém revisita. restart_app_servicedeploy_to_app_serviceset_app_service_settingsconfigure_app_servicecreate_app_service
Em um plano Standard ou Premium, um portal pode ter slots de implantação, cada um rodando contra seu próprio ambiente Dataverse — um uat slot contra UAT, enquanto produção roda contra produção. create_deployment_slot cria um e o conecta ao ambiente, então quando você trabalha em UAT e pede uma implantação, a build vai para o slot UAT em vez de para produção. As configurações que nomeiam um ambiente são marcadas para permanecer com seu slot, então swap_slots podem promover a build testada para produção e ela inicia contra os dados de produção. Uma troca é recusada quando isso levaria um ambiente para outro.
Nota
Esses não usam a CLI do Azure e nunca leem ou mudam seu estado de logado. Execute
ppp-mcp azure loginna pasta: assim como o vinculante Dataverse, a assinatura pertence apenas a essa pasta, então vários projetos podem direcionar diferentes clientes ao mesmo tempo.az account showNão diz nada sobre o que essas ferramentas vão fazer.
Inscrições no aplicativo Entra
Os dois registros que um portal precisa, e os trabalhos que os seguem. Esses são os passos que atrasam a maioria das configurações: são dois registros separados em vez de um, o aplicativo de login precisa de uma URL de resposta carregando uma porta que o template randomizou, e um cliente secreto caduca um ano depois e impede o portal de começar com um erro que nunca menciona o Entra.
add_app_registration_certificate Sign in as an app with a Key Vault certificate, no secret
add_app_registration_federated_credential Let a managed identity be an app's credential, no secret
add_app_registration_redirect_uri Add the production reply URL after a deployment
add_app_registration_secret Rotate a secret before it lapses
add_table_privileges_to_role Give your own role access to a table (never a managed one)
assign_application_user_column_profile Grant the secured contact columns a role cannot
assign_application_user_role Grant the application user a security role
create_dataverse_app_registration The backend identity the portal reads Dataverse as
create_dataverse_application_user The Dataverse half, with its security role
create_security_role An empty role of your own, for your tables' privileges
create_signin_app_registration The app behind "Sign in with Microsoft"
delete_security_role Delete a role of your own that nobody holds any more
describe_role_table_privileges What a role grants on one table, and at what depth
get_application_user Does Dataverse know this client id, and what may it do?
list_app_registrations Client ids, reply URLs and secret expiry dates
list_security_roles What roles the environment offers
remove_app_registration_certificate Retire an old certificate after a rotation
remove_application_user_column_profile Take back the secured contact columns
remove_application_user_role Take back a security role
remove_table_privileges_from_role Take a table's privileges back from a role, or lower them
As ferramentas não têm direitos próprios. Cada chamada é feita por um token delegado para a conta com a qual você fez login, emitido para um cliente público que não guarda segredo — então cada operação tem sucesso exatamente quando você poderia ter feito manualmente no portal, e é recusada com um 403 nomeando o papel de diretório que você precisaria quando não pudesse. Faça login como Desenvolvedor de Aplicações com conta ou superior e isso funciona; faça login como qualquer outra pessoa e eles não podem causar dano. Nenhuma permissão de API é solicitada e nenhum consentimento de administrador é concedido, pois nenhum dos registros precisa de nenhum.
Ambas as metades, porque nenhuma funciona sozinha. Um registro de aplicativo recebe um token; um usuário de aplicação Dataverse decide o que esse token pode fazer. Um registro sem um autentica perfeitamente e é recusado por cada chamada, o que parece uma conexão quebrada em vez de um objeto ausente — e um usuário de aplicativo sem função de segurança é criado, visível, aparentemente aceitável e autorizado a não fazer nada. create_dataverse_application_user faz a segunda metade e atribui o papel na mesma etapa. Este é o único lugar onde o servidor escreve fora de suas próprias três tabelas, admitido porque o usuário da aplicação é infraestrutura e não dados do cliente; nenhuma ferramenta cria, altera ou exclui um registro de negócios.
Eles trabalham em registros que já existem. Cada create_*_registration ferramenta aceita um clientId, e com um deles ela adota esse registro em vez de criar um — adiciona um segredo, integra quaisquer novas URLs de resposta, escreve as credenciais onde você pediu. A confirmação então diz para adicionar um segredo ao registro existente em vez de criar, então você nunca está aprovando uma operação e recebendo outra. As ferramentas que alteram um registro existente, add_app_registration_redirect_uri e add_app_registration_secret, pegam também um ID de cliente e preferem: nomes de exibição não são únicos, e um inquilino com três registros chamado "Portal" é normal.
Um segredo de cliente criado não é devolvido por padrão. Ele vai direto da resposta do Graph para os segredos de usuário do projeto, uma configuração de aplicativo de aplicativo, ou ambos, e a ferramenta informa para onde foi e quando expira, em vez do que era. Quando um segredo precisa chegar a algum lugar que o servidor não pode escrever — máquina de um colega, um armazenamento secreto de CI, um cofre em outra assinatura — peça destination: "return" e o valor é mostrado para você copiar. A confirmação diz isso antes de você concordar, e o resultado traz o aviso que o merece: o segredo está então na transcrição, então trate-o como exposto se essa transcrição estiver armazenada, e rotative-o se houver dúvidas. Segredos são cunhados por 24 meses por padrão — o maior tempo que o portal da Entra oferece — porque a falha que esse framework realmente sofre é um segredo caducado, e não um roubado: o portal para de começar em uma data que ninguém notou, com um erro que nunca menciona o Entra. Esse limite pertence à interface do portal, não à API, então expiryMonths aceita até 120 (10 anos), quando você prefere rodar uma vez a cada cinco anos do que correr o risco de uma falha. Não é o padrão, porque uma credencial que nenhum administrador poderia ter criado manualmente é algo surpreendente de encontrar — então a confirmação diz quantos anos você pediu e que o portal não conseguiu produzi-la.
Um aplicativo pode fazer login com um certificado em vez de um segredo.add_app_registration_certificate cria um certificado no Key Vault cuja chave privada nunca pode ser exportada, e adiciona sua metade pública ao registro. Vincule um ambiente a esse app ppp-mcp login --environment <url> --client-id <id> --certificate <url> e o cofre assina cada login para quem detiver o Key Vault Crypto User nele, para que nenhum segredo fique em nenhuma máquina. Para rodar, execute a mesma ferramenta novamente;remove_app_registration_certificate aposenta o certificado antigo assim que nada mais o usar.
Nota
Duas coisas estão deliberadamente faltando. Deletar um registro pode derrubar o login de cada aplicação em um tenant e só pode ser recuperado dentro de um prazo de 30 dias. Conceder consentimento do administrador é a operação que transforma um ato delegado restrito em uma permissão permanente para todo o inquilino. Nenhuma das duas é necessária para fazer um portal funcionar, então nenhuma é oferecida. Criar o usuário da aplicação Dataverse para o novo id de cliente também é uma etapa separada — a saída da ferramenta fornece o comando.
Removendo o segredo que expira
Um cliente secreto é a parte de um portal implantado que para de funcionar em uma data que ninguém anotou. Esses o removem ou movem o que resta para algum lugar que possa ser rotacionado sem necessidade de reimplantação.
create_key_vault A vault the managed identity can read, for the secrets that remain
create_managed_identity A user-assigned identity, independent of any one app
enable_managed_identity Attach a managed identity to the App Service
list_user_secret_keys The keys in the project's user secrets — names, never values
push_secrets_to_key_vault Copy the user secrets you approve into the vault, and point the app at them
Definido D365__ManagedIdentityId para o id de cliente da identidade — não para o id de objeto ou principal que o portal Azure mostra primeiro — e dê a esse id de cliente seu próprio usuário de aplicação Dataverse, com create_dataverse_application_user como qualquer outro. O portal então se conecta sem nenhum segredo.
O remetente do e-mail
O portal envia e-mails de confirmação e redefinição de senha de um endereço que precisa ser resolvido para uma fila ou um usuário habilitado no Dataverse. create_email_queue cria a fila, aprova sua caixa de correio e executa o Test & Enable, reportando o resultado; check_email_sender explica por que um remetente não está entregando. Uma fila, e não a caixa de correio de uma pessoa, é o remetente correto para um endereço sem resposta.
check_email_sender Why mail from the sender address is not arriving, and what to fix
create_email_queue A queue for the portal's outbound mail, approved and tested
list_email_queues The queues in the environment, and the addresses they send from
Importante
Duas coisas que ele não pode fazer por você. O endereço precisa de uma caixa de correio no Exchange Online — uma caixa de correio compartilhada, que não precisa de licença — e apenas um Administrador Global do Office 365 ou um Administrador do Exchange pode aprová-lo. Quando algum deles está faltando, a ferramenta diz qual, e executá-la novamente quando for corrigida termina o trabalho. Até que o Test & Enable passe, o Dataverse aceita o e-mail do portal e não entrega nada — indistinguível de sucesso do lado do portal, por isso a ferramenta testa em vez de reportar um resultado limpo.
Trabalhando em outras línguas
O conhecimento que o servidor retorna é em inglês, e isso é deliberado. Seu assistente é quem está lendo — você nunca vê uma resposta de ferramenta diretamente — então ele traduz para você: pergunte no seu próprio idioma, e ele responde no seu idioma. O que ele não deve traduzir é o código. Os nomes dos componentes, parâmetros e colunas são em inglês em todo projeto, seja qual for o idioma da conversa, então manter a referência em inglês é o que impede um assistente de inventar um nome de parâmetro traduzido que não existe.
Nota
Perguntas que nomeiam algo —
“MainGrid Ansichten konfigurieren”— já funcionam em qualquer idioma, porque os nomes dos componentes são os mesmos em todos os lugares. As ferramentas também pedem ao seu assistente para pesquisar em inglês, então perguntas que não nomeiam nada também funcionam.
Solução de problemas
- "Nenhum ambiente Dataverse está vinculado a esta pasta do projeto" — execute
loginnessa pasta. Verifique se você está na pasta que acha que está:statusimprime a raiz do workspace que ela resolveu. - "O login salvo não é mais válido" — o token de atualização expirou ou foi revogado, ou o locatário agora precisa de uma nova interação. Execute
loginnovamente. - "O keystore do sistema operacional não está disponível" — comum em um computador Linux headless sem daemon libsecret. Use um principal de serviço lá, via as
PPP_D365_*variáveis de ambiente. - Entrei logado, mas o ambiente rejeita a conexão — a conta foi autenticada, mas não tem acesso a esse ambiente. Verifique a URL ou faça login como um usuário diferente com
--username.
