# Credentials

Whose credential a call to an MCP server carries, and why the agent never holds it.

In short: A server that needs a credential checks it on every call, and the agent never holds it. The gateway adds the credential the server declares, either the server's own secret, which Straza stores, or the caller's own token or sign-in. Straza uses a separate listing credential only on its own call that lists a server's objects.


Acredentialisthesecretthatan[MCPserver](https://docs.straza.ai/concepts/mcp-apps-and-the-gateway/index.md)checksbeforeitanswersacall.Strazastoreseverysuchcredential,andthegatewayaddsittoacallonlyafterthecallisdecided.##WhytheagentneverholdsitStrazadoesnothandan[agent](https://docs.straza.ai/concepts/identities/index.md)itsowncredentialsandtrusttheagent'smachinetousethemwell.Themodelcanread,printandsendanycredentialontheagent'smachine,andnohookonanopenmachinecanstopaprocessthatalreadyholdsone.Becausethesecretiskeptonthegateway,callsonthegatewaypathstaygovernedevenwhenthecontrolsontheagent'smachinefail.Thisprotectioncoversonlycallsthatpassthroughthegateway.Anagentthathasitsownrouteoritsowncredentialtoaservercanskipthegateway,soremovethoserouteswhenyoudeploy.##WhosecredentialacallcarriesTheserver'smanifestdeclareswhichcredentialitneeds,andthegatewayresolvesitforeachcallfromthesessionthatmakesit.|Theserverneeds|Thecallcarries|WhoputsitinStraza||---|---|---||Nothing|Nocredential|Nobody||Onesharedsecret|Theserver'sownsecret,ortheoverrideofthe[role](https://docs.straza.ai/concepts/roles-and-access/index.md)thatallowedthecall|Anadminoftheserver||Eachperson'sowntoken|Thecaller'sowntoken|Eachperson,once,ontheirself-servicepageorfromaterminal||Eachperson'sownsign-in|Thecaller'sownsign-inataprovideranadminregistered|Eachperson,once,inabrowser|Onthedemostack,theserverpostgrestakesonesharedsecret.Thegatewaysendsittoadaptive-pg-mcpasabearerheaderoneverycall.Allitscallersreachthedatabaseasthesameupstreamidentity,andonlyStraza'srecordstellthemapart.[Credentials](https://docs.straza.ai/guides/serve-mcp-apps/credentials/index.md)storesasharedsecret,and[Eachcaller'sowncredential](https://docs.straza.ai/guides/serve-mcp-apps/caller-credentials/index.md)setsuptokensandsign-ins.Asharedsecretgoestoaremoteserverasaheader,andtoaserverthatrunsasaprocessinitsenvironment.Atokenorasign-inofeachcallerworksonlywitharemoteserver,becauseaprocessisoneidentityandcannotcarryacredentialpercaller.Strazadeniesapersonwhohasnotokenorsign-inoftheirown,andapersonneverfallsbacktoanothercredential.Anagentwithnoneofitsownrunsonwhatthemanifestnamesforagents:nothing,its[sponsor's](https://docs.straza.ai/concepts/identities/index.md)owncredentialoncethesponsorhasallowedit,ortheserver'ssharedsecret.Onaserverthattakeseachcaller'ssign-in,anagentcanalsogetatokenofitsownclientattheprovider.The[auditrecord](https://docs.straza.ai/concepts/evidence/index.md)ofeachcallnameswhichcredentialitusedandwhoseitwas,soareviewcantellanagentonitssponsor'saccountfromthesponsor'sowncalls.##WhereitiskeptandwhocanseeitStrazasealseachstoredcredentialwithitskey-encryptionkeyandkeepsonlytheciphertext.Itholdsthesealedrowsinmemory,soacallneverreadsthedatabase,andopensarowonlywhenacallorahealthcheckneedsit.NoAPIresponseevercarriesthevalue.Peoplerecognizeastoredsecretbyitsfingerprint,thefirstfourhexcharactersofitsSHA-256.Theagent'sownStrazasessiontokenneverreachestheserver,becausethegatewayneverforwardsaclient'sauthorizationheader.Whenacallneedsacredentialandnonecanbefound,thegatewaydeniesitwithasentencethatsayswhostoresone,anditnevercallstheserverwithoutit.Theserverdoesreceivethecredentialandcananswerwithcontentofitsown,soyoumuststilltrusttheserver.##ThelistingcredentialAserverthatdeclaresits[objects](https://docs.straza.ai/concepts/objects/index.md)needsanotherstoredsecret,thelistingcredential.Strazacallstheserver'slisttoolitself,withnoperson'ssessionbehindthecall,andthatcallcarriesonlythelistingcredential.Notoolcallandnohealthcheckcarriesit,andthelistingneverfallsbacktoanothersecret.Onthedemostack,everytoolcalltopostgrescarriestheserver'sownsecret,andonlyStraza'slistingof`list_databases`carriesitslistingcredential.Nopersonstandsbehindthelistingcredential,soaservershouldacceptitonlyonitslisttool.Aserverthatalsoaccepteditonitswritetoolswouldletthatcredentialbypasseveryrole.##Straza'sowncredentialsThekeysandsessiontokensthatprovewhoiscallingStrazaitselfareseparatefromthecredentialsoftheserversbehindthegateway.[Credentialsandsessions](https://docs.straza.ai/security/credentials-and-sessions/index.md)followsthemfromenrollmenttorevocation.Whatanexpertasksaboutcredentials:Foraserverwithasharedsecret,thegatewayusesthefirstcredentialitfindsinthisorder:anoverrideontherolethatallowedthecall,theoverrideoftheheldrolewhosenamesortsfirst,andtheserver'sownsecret.Onaserverthatdeclaresobjects,therolethatallowedthecallisthefirstrolebynamethatcoversit.Thehealthcheckusestheserver'sownsecret,orthefirstroleoverridebynamewhenthereisnone.Strazadoesnotreachaserverthattakesasharedsecretuntilthesecretisstored,soanewlyaddedserverofthatkindlistsnotoolsuntilthen.Aserverthatrunsasaprocessdoesnotstartuntilitssecretarrives.Whenaperson'sowntokenorsign-inhasexpiredorcannotbeopened,thegatewaydeniesthecallandneverfallsthroughtoanothercredential.Eachperson'stokenissealedunderthesamekeyaseveryothercredential.Thereisnokeyperperson,becausethegatewaymustopenthetokenforanagent'scallswhileitspersonisaway.Nobodycanfinishasign-inforanagent,becauseasign-infinishesinabrowserthatissignedintoStrazaasaperson.Anagentonasign-inserverthereforerunsonitssponsor'ssign-in,asharedsecret,oritsownclient.When[yourIGA](https://docs.straza.ai/evaluate/identity-and-your-iga/index.md)deactivatesaperson,Strazadeletesthatperson'sowntokensandsign-ins.Apersonmadeactiveagainconnectsthoseserversagain.Strazastoresamanifestasitwaswrittenandmaskssecret-shapedvaluesonlywhenitshowsone.Asecrettypedintothemanifestitselfthereforesitsinclearinthedatabaseanditsbackups.Putitinastoredcredentialinstead.Next:[Auditandevidence](https://docs.straza.ai/concepts/evidence/index.md)



