Tracing Every Place a PeopleSoft Field Is Updated Using an AI Agent and the psLens MCP Server

A real-world walkthrough of how an AI coding agent used the psLens Model Context Protocol (MCP) server to trace every PeopleCode program, App Package, App Engine, record default, and COBOL SQL statement that sets STDNT_CAR_TERM.TUIT_CALC_REQ to ‘Y’.

Every PeopleSoft developer and functional analyst has been asked a version of this question:

“Where in the system does STDNT_CAR_TERM.TUITION_CALC_REQ get set to 'Y'?”

On a traditional codebase stored in Git, ripgrep answers that question in two seconds. In PeopleSoft, a single flag can be flipped across seven different architectural layers:

  • Record Field Defaults stored in PSRECFIELD (DEFFIELDNAME / DEFRECNAME)
  • Record Field PeopleCode (RowInit, FieldChange, SavePreChange, SavePostChange)
  • Scroll Buffer Functions (UpdateValue() targeting the record or a view over the record)
  • Database Views (STDNT_CAR_TE_VW) that write through to the underlying table
  • Inline SQLExec Statements with hardcoded UPDATE PS_STDNT_CAR_TERM strings
  • Application Packages & Application Engine Programs (both PeopleCode and SQL actions)
  • COBOL Stored SQL Statements in PS_SQLSTMT_TBL
  • Online Pages and Component Interfaces where users or integrations toggle the field directly

Worse, raw text searches in Application Designer or against PSPCMTXT routinely return false positives from commented-out code (/* ... */ or REM), miss updates that happen through SQLExec("UPDATE PS_STDNT_CAR_TERM ..."), and ignore COBOL stored SQL entirely.

Here is what happens when you hand that exact prompt to an AI coding agent connected to a PeopleSoft Campus Solutions 9.2 environment through the psLens MCP Server.


The Prompt

The entire investigation started with a single one-line prompt in the IDE:

Use pslens to find all areas where STDNT_CAR_TERM.TUITION_CALC_REQ gets set to "Y".

Notice the subtle trap in the prompt itself: the human asked for TUITION_CALC_REQ (after the page label “Tuition Calc Required”), whereas the actual PeopleSoft column name on STDNT_CAR_TERM is truncated to 13 characters: TUIT_CALC_REQ.

Here is the exact sequence of MCP tool calls the agent executed to resolve the schema, trace every dependency layer, verify the source code, and eliminate false positives.

flowchart TD
    P["User Prompt:\nFind where STDNT_CAR_TERM.TUITION_CALC_REQ = 'Y'"]
    T1["list_databases\nIdentify connected CS 9.2 instance"]
    T2["get_record_schema\nInspect STDNT_CAR_TERM fields & defaults"]
    T3["analyze_record_field_impact\nBlast radius across pages, CIs, views & PeopleCode"]
    T4["search_code_sql\nSearch PeopleCode, App Engine SQL & SQL Objects"]
    T5["query_table (SQLSTMT_TBL)\nInspect COBOL stored UPDATE/INSERT statements"]
    T6["get_peoplecode\nRead full event source & filter commented-out code"]
    R["Complete Cross-Layer Impact Report"]

    P --> T1 --> T2 --> T3 --> T4 --> T5 --> T6 --> R

Step-by-Step: How the Agent Used the psLens MCP Tools

Discovering the Environment and Resolving the Field Name

First, the agent called list_databases to see which PeopleSoft environments were connected, followed by get_record_schema on STDNT_CAR_TERM:

{
  "tool": "get_record_schema",
  "arguments": {
    "db": "CS92DEV-CHG",
    "record_name": "STDNT_CAR_TERM"
  }
}

From get_record_schema, the agent immediately spotted two critical facts without human intervention:

  • The column on STDNT_CAR_TERM is TUIT_CALC_REQ (not TUITION_CALC_REQ).
  • In PSRECFIELD, STDNT_CAR_TERM.TUIT_CALC_REQ has a Record Field Default pointing to BUS_UNIT_TBL_SF.TERM_ACT_INIT_SET (Term Activation Initial Setting). Whenever TERM_ACT_INIT_SET = 'Y' on the Student Financials Business Unit, any new STDNT_CAR_TERM row or SetDefault(STDNT_CAR_TERM.TUIT_CALC_REQ) call automatically initializes TUIT_CALC_REQ to 'Y'.

Running a Record.Field Blast Radius Analysis

Next, the agent called analyze_record_field_impact to map every PeopleSoft object that references STDNT_CAR_TERM.TUIT_CALC_REQ:

{
  "tool": "analyze_record_field_impact",
  "arguments": {
    "db": "CS92DEV-CHG",
    "record_name": "STDNT_CAR_TERM",
    "field_name": "TUIT_CALC_REQ"
  }
}

In a single round trip, analyze_record_field_impact returned:

  • Online Pages displaying STDNT_CAR_TERM.TUIT_CALC_REQ (STDNT_TUITION_CALC, WITHDRAWAL, QUICK_ADMIT_WRK2, OEE_ENRL_DATES) and whether each page field is editable or display-only.
  • Component Interfaces exposing the field and their access mode (ENRL_GRADES and ENRL_TERM_ACTIVTN as Read/Write; CHI_STDNT_ACTIVATION as Read-Only).
  • Direct PeopleCode References to STDNT_CAR_TERM.TUIT_CALC_REQ.

Searching PeopleCode, App Engine SQL, and SQL Objects

Direct RECORD.FIELD metadata references only tell part of the story. In Campus Solutions, many programs update PS_STDNT_CAR_TERM via raw SQLExec("UPDATE PS_STDNT_CAR_TERM SET TUIT_CALC_REQ = 'Y' ..."), through the view STDNT_CAR_TE_VW, or via Application Engine SQL actions.

The agent invoked search_code_sql across peoplecode, appengine, and sqlobject scopes:

{
  "tool": "search_code_sql",
  "arguments": {
    "db": "CS92DEV-CHG",
    "query": "TUIT_CALC_REQ",
    "scope": "all"
  }
}

This surfaced 89 PeopleCode matches and all Application Engine SQL steps referencing TUIT_CALC_REQ, including batch SQL updates in the Student Group process (SCC_STD_GRP steps MVOVRD.MVOVRD45 and MVTRGT.MVTRGT45) and SQLExec updates buried inside Residency (RESIDENCY_OFF), Optional Fees (OPT_FEE_STDNT), Student Equation Variables (STDNT_EQUTN_VAR), Student Groups (STDNT_GRPS), and Student Waivers (SSF_STD_WAIVER / SSF_SWVR_PS).

Checking COBOL Stored SQL in SQLSTMT_TBL

Campus Solutions relies heavily on COBOL batch programs (SRPCENRL, SRPCCUMM, SFPBCALC, SFPRCALC) whose SQL statements live in PS_SQLSTMT_TBL, completely outside App Designer’s PeopleCode and SQL definitions.

Using query_table, the agent queried SQLSTMT_TBL for statements touching TUIT_CALC_REQ or updating PS_STDNT_CAR_TERM:

{
  "tool": "query_table",
  "arguments": {
    "db": "CS92DEV-CHG",
    "record_name": "SQLSTMT_TBL",
    "fields": ["PGM_NAME", "STMT_TYPE", "STMT_NAME", "STMT_TEXT"],
    "filters": [
      { "field": "STMT_TEXT", "op": "like", "value": "%TUIT_CALC_REQ%" }
    ],
    "limit": 100
  }
}

That query separated the COBOL programs that clear the flag (SFPBCALC, SFPBHECS, SFPCCALC, SFPCLCAN, SFPRCALC, SFPREFND, which all run SET TUIT_CALC_REQ = 'N') from the COBOL program that updates it during enrollment and term statistics processing: SRPCCUMM (STMT_NAME = 'CUMTERM'), which executes:

UPDATE PS_STDNT_CAR_TERM
   SET ...,
       FA_STATS_CALC_REQ = 'Y',
       TUIT_CALC_REQ = :54,
       ...
 WHERE EMPLID = :63
   AND ACAD_CAREER = :64
   AND INSTITUTION = :65
   AND STRM = :66

Reading Full Event Context and Catching Commented-Out Code

A substring search for TUIT_CALC_REQ matched STDNT_CAR_SEQ.STDNT_CAR_NBR.SavePreChange at line 156:

UpdateValue(STDNT_CAR_TE_VW.TUIT_CALC_REQ, &I, "Y");

If you only look at a single matching line from a grep or SQL query on PSPCMTXT, you would list STDNT_CAR_SEQ.STDNT_CAR_NBR.SavePreChange as an active trigger. Instead, the agent called get_peoplecode to inspect the surrounding program:

{
  "tool": "get_peoplecode",
  "arguments": {
    "db": "CS92DEV-CHG",
    "name": "STDNT_CAR_SEQ.STDNT_CAR_NBR",
    "event_or_step": "SavePreChange"
  }
}

Inspecting the full PeopleCode event revealed that Oracle had wrapped lines 150–159 of STDNT_CAR_SEQ.STDNT_CAR_NBR.SavePreChange inside a /* ... */ block comment and moved the active logic to DERIVED_CS.ROW_NUMBER.SavePreChange! The agent also used get_peoplecode on STDNT_CAR_TERM.REG_CARD_DATE.SavePreChange to extract the exact list of 20 FieldChanged(...) conditions that trigger tuition recalculation when a student’s term record is edited.


The Complete Research Output

Within seconds, the agent produced a complete inventory of every mechanism that sets STDNT_CAR_TERM.TUIT_CALC_REQ to 'Y':

Record Field Default (PSRECFIELD)

  • STDNT_CAR_TERM.TUIT_CALC_REQ (and STDNTCARTERM_DR.TUIT_CALC_REQ) defaults from BUS_UNIT_TBL_SF.TERM_ACT_INIT_SET. When TERM_ACT_INIT_SET = 'Y', any new row or SetDefault(STDNT_CAR_TERM.TUIT_CALC_REQ) call (such as in STDNT_CAR_TERM.STRM.FieldChange line 41 and STDNT_CAR_TERM.STDNT_CAR_NBR.FieldChange line 40) sets TUIT_CALC_REQ to 'Y'.

Record Field PeopleCode

  • STDNT_CAR_TERM.EMPLID.RowInit (line 362): Sets STDNT_CAR_TERM.TUIT_CALC_REQ = "Y" when %Mode = "A" (Add mode).
  • STDNT_CAR_TERM.REG_CARD_DATE.SavePreChange (line 33): In TERM_HISTORY or STDNT_ACTIVATION, sets STDNT_CAR_TERM.TUIT_CALC_REQ = "Y" on an existing term row if any of these 20 fields on STDNT_CAR_TERM changed: ACADEMIC_LOAD, ACAD_LEVEL_BOT, ACAD_LEVEL_PROJ, ACAD_LOAD_APPR, STDNT_CAR_NBR, ACAD_PROG_PRIMARY, ACAD_YEAR, BILLING_CAREER, CUR_RESIDENT_TERMS, TRF_RESIDENT_TERMS, ELIG_TO_ENROLL, FORM_OF_STUDY, FULLY_ENRL_DT, LAST_DATE_ATTENDED, PROJ_BILL_UNT, OVRD_BILL_UNITS, WITHDRAW_CODE, WITHDRAW_DATE, INSTITUTION, or STRM.
  • STDNT_CAR_TERM.OVRD_TUIT_GROUP.FieldChange (line 3): In STDNT_ACTIVATION or TUITION_CALC, sets STDNT_CAR_TERM.TUIT_CALC_REQ = "Y" when OVRD_TUIT_GROUP changes.
  • DERIVED_CS.ROW_NUMBER.SavePreChange (line 26): In ACAD_PLAN (Student Program/Plan), sets STDNT_CAR_TE_VW.TUIT_CALC_REQ = "Y" for terms >= &TERM when ACAD_PROG.PROG_STATUS is "AC", "AD", or "AP".
  • DERIVED_CS.UPDATE_CUM.SavePreChange (line 23) & FUNCLIB_CS.TOT_CUMULATIVE.FieldFormula (get_cur_term, line 426): Set STDNT_CAR_TERM.TUIT_CALC_REQ to "Y" via UpdateValue(STDNT_CAREER.EMPLID, ..., STDNT_CAR_TERM.TUIT_CALC_REQ, 1, "Y") when updating term/cumulative enrollment statistics.
  • STDNT_ENRL_OEE.END_DT.FieldChange (lines 2–3): In OEE_CALENDAR, sets GetLevel0()(1).STDNT_CAR_TERM(1).STDNT_CAR_TERM.TUIT_CALC_REQ.Value = "Y".
  • SSR_HECS_ELEC.SSR_HECS_XMPT_STAT.SavePreChange (line 3): Sets STDNT_CAR_TERM.TUIT_CALC_REQ = "Y" when FieldChanged(SSR_HECS_ELEC.SSR_HECS_XMPT_STAT).
  • RESIDENCY_OFF.INSTITUTION.SavePostChange (lines 14, 16, 21): In RESIDENCY_ADMA, RESIDENCY_ADMP, or RESIDENCY_PERS, when DERIVED_CC.TUIT_CALC_REQ = "Y" (set by FieldChange on RESIDENCY_OFF.EFFECTIVE_TERM, INSTITUTION, RESIDENCY, or TUITION_RES) or when a residency row is deleted, runs SQLExec("UPDATE PS_STDNT_CAR_TERM SET TUIT_CALC_REQ = 'Y' WHERE EMPLID = :1 AND ACAD_CAREER = :2 AND INSTITUTION = :3 AND STRM >= :4", ...).
  • OPT_FEE_STDNT.VALID_VALUE.SavePreChange (line 5): When RecordChanged(OPT_FEE_STDNT.VALID_VALUE), runs SQLExec("update ps_stdnt_car_term set tuit_calc_req = 'Y' where emplid = :1 and institution = :2 and strm = :3 and billing_career = :4", ...).
  • STDNT_EQUTN_VAR.STRM.SavePostChange (lines 7, 10): Runs SQLExec("UPDATE PS_STDNT_CAR_TERM SET TUIT_CALC_REQ = 'Y' WHERE EMPLID = :1 AND BILLING_CAREER = :2 AND INSTITUTION = :3 AND STRM = :4", ...) for both STDNT_EQUTN_VAR.STRM and &PRIOR_TERM.
  • STDNT_GRPS.INSTITUTION.SavePostChange (lines 32, 49, 71): In STDNT_GROUPS_ADMA, STDNT_GROUPS_ADMP, or STDNT_GROUPS_PERS, when &TUIT_RECALC_REQ = "Y" (or a student group row is deleted), runs SQLExec("UPDATE PS_STDNT_CAR_TERM SET TUIT_CALC_REQ = 'Y' WHERE EMPLID = :1 AND INSTITUTION = :2 AND ACAD_CAREER = :3 AND STRM = :4", ...) for terms with TERM_BEGIN_DT >= &STDNT_GROUP_EFFDT.

Application Package PeopleCode

  • SSR_CAREER_TERM:Accessors:StudentTerm (OnExecute):
    • Lines 1284 / 4268: Sets %This.TUIT_CALC_REQ = &recBUS_UNIT_TBL_SF.TERM_ACT_INIT_SET.Value during term creation.
    • Lines 1785 / 4769: Sets %This.TUIT_CALC_REQ = "Y" using the same field-change rules as STDNT_CAR_TERM.REG_CARD_DATE.SavePreChange.
    • Lines 2629 / 5613: Property setter set TUIT_CALC_REQ assigns %This.data.TUIT_CALC_REQ.Value = &NewValue.
  • SSR_FA_DATA_UPD:ProcessFAUnits (OnExecute, line 244): Sets &REC_stdntcarTerm.TUIT_CALC_REQ.Value = "Y" and updates STDNT_CAR_TERM.
  • SCC_POP_UPDATE:APEngine:STDNT_EQUTN_VAR (line 63), SCC_POP_UPDATE:APEngine:PopUpdateCommonProcessing (lines 734, 1234), and SCC_POP_UPDATE:APEngine:RowByRowProcessing (lines 734, 1234):
    • When Population Update inserts or updates STDNT_EQUTN_VAR, it loads STDNT_CAR_TERM by key, sets &StudentCarTerm.TUIT_CALC_REQ.Value = "Y", and calls .Update().
    • When Population Update modifies STDNT_CAR_TERM.OVRD_TUIT_GROUP, it also sets TUIT_CALC_REQ to "Y".
  • SSF_TUITION_AND_FEES:Components:SSF_STD_WAIVER (OnExecute, line 414): Runs SQLExec("UPDATE PS_STDNT_CAR_TERM SET TUIT_CALC_REQ = 'Y' WHERE EMPLID = :1 AND INSTITUTION = :2 AND STRM = :3", SSF_STDNT_WVR.EMPLID, &Institution, SSF_STDNT_WVR.STRM) when saving student waivers.

Application Engine Programs

  • SSF_SWVR_PS (LINEPROC.OnExecute PeopleCode, line 11): Runs SQLExec("UPDATE PS_STDNT_CAR_TERM SET TUIT_CALC_REQ = 'Y' WHERE EMPLID = :1 AND INSTITUTION = :2 AND STRM = :3", SSF_SWVR_PS_AET.EMPLID, &Institution, SSF_SWVR_PS_AET.STRM).
  • SCC_STD_GRP (MVOVRD.MVOVRD45 and MVTRGT.MVTRGT45 SQL actions): Updates PS_STDNT_CAR_TERM A SET A.TUIT_CALC_REQ = 'Y' where STDNT_GRP_AET.TUIT_CALC_REQ_LBL = 'Y', A.TUIT_CALC_REQ = 'N', and TERM_BEGIN_DT >= ASOFDATE.

COBOL Stored SQL (SQLSTMT_TBL)

  • SRPCCUMM (CUMTERM): Updates PS_STDNT_CAR_TERM SET ..., FA_STATS_CALC_REQ = 'Y', TUIT_CALC_REQ = :54, ... during enrollment and cumulative statistics processing (SRPCENRL / SRPCENVB).

Online Pages & Component Interfaces

  • Online Pages: STDNT_CAR_TERM.TUIT_CALC_REQ is directly editable on STDNT_TUITION_CALC (components STDNT_ACTIVATION and TUITION_CALC), WITHDRAWAL (component TERM_HISTORY), and QUICK_ADMIT_WRK2 (component QUICK_ADMIT).
  • Component Interfaces: Exposed as Read/Write (BCACCESS = 2) on ENRL_GRADES and ENRL_TERM_ACTIVTN.

Why This Changes PeopleSoft Impact Analysis

Answering this question manually in Application Designer typically takes an experienced PeopleSoft developer an hour or more of cross-referencing Find Definition References, Find In across PeopleCode and SQL, checking record field properties, and writing custom SQL against PS_SQLSTMT_TBL — assuming they even remember to check views like STDNT_CAR_TE_VW and COBOL stored statements.

With the psLens MCP Server, an AI agent in Google Antigravity, Claude Code, Cursor, or VS Code has read-only, whitelisted access to the entire PeopleSoft metadata graph and code repository:

MCP Tool UsedRole in the Investigation
list_databasesIdentified the target Campus Solutions 9.2 database (CS92DEV-CHG)
get_record_schemaResolved TUITION_CALC_REQ → TUIT_CALC_REQ and uncovered the BUS_UNIT_TBL_SF.TERM_ACT_INIT_SET default
analyze_record_field_impactMapped every page, component, Component Interface, and direct PeopleCode reference
search_code_sqlFound inline SQLExec("UPDATE PS_STDNT_CAR_TERM ...") calls, view updates (STDNT_CAR_TE_VW), and App Engine SQL actions
query_tableInspected COBOL stored SQL statements in PS_SQLSTMT_TBL (SRPCCUMM vs. SFPBCALC)
get_peoplecodeVerified full event logic, extracted the 20 trigger fields on REG_CARD_DATE.SavePreChange, and filtered out commented-out legacy code

Try It on Your Own Environment

The embedded MCP server ships inside psLens with zero extra infrastructure required:


Subscribe for Updates

If you found this article helpful, subscribe to get notified of new PeopleSoft technical notes and psLens updates.

Stay Updated

Receive new articles directly in your inbox.